Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9b1cee6

Browse files
cartermpKevinRansom
authored andcommitted
Update tutorial script to include immutability and pipelines (dotnet#2129)
* Update tutorial script to include immutability and pipelines* Updates/feedback
1 parent51ba1ef commit9b1cee6

File tree

1 file changed

+107
-6
lines changed
  • vsintegration/ProjectTemplates/TutorialProject/Template

1 file changed

+107
-6
lines changed

‎vsintegration/ProjectTemplates/TutorialProject/Template/Tutorial.fsx‎

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
/// To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/xml-documentation
3737
3838

39-
// Open namespaces using the 'open'directive.
39+
// Open namespaces using the 'open'keyword.
4040
//
4141
// To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/import-declarations-the-open-keyword
4242
openSystem
@@ -64,10 +64,32 @@ module IntegersAndNumbers =
6464
/// This is a list of all tuples containing all the numbers from 0 to 99 and their squares.
6565
letsampleTableOfSquares=[for iin0..99->(i, i*i)]
6666

67-
// The next line prints a list that includes tuples, using%A for generic printing.
67+
// The next line prints a list that includes tuples, using'%A' for generic printing.
6868
printfn"The table of squares from 0 to 99 is:\n%A" sampleTableOfSquares
6969

7070

71+
/// Values in F# are immutable by default (save for Arrays). They cannot be changed
72+
/// in the course of a program's execution unless explicitly marked as mutable.
73+
///
74+
/// To learn more, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/values/index#why-immutable
75+
moduleImmutability=
76+
77+
/// Binding a value to a name via 'let' makes it immutable.
78+
///
79+
/// The second line of code fails to compile because 'number' is immutable and bound.
80+
/// Re-defining 'number' to be a different value is not allowed in F#.
81+
letnumber=2
82+
// let number = 3
83+
84+
/// A mutable binding. This is required to be able to mutate the value of 'otherNumber'.
85+
let mutableotherNumber=2
86+
87+
// When mutating a value, use '<-' to assign a new value.
88+
//
89+
// Note that '=' is not the same as this. '=' is used to test equality.
90+
otherNumber<- otherNumber+1
91+
92+
7193
/// Much of F# programming consists of defining functions that transform input data to produce
7294
/// useful results.
7395
///
@@ -94,7 +116,7 @@ module BasicFunctions =
94116

95117
/// Conditionals use if/then/elid/elif/else.
96118
///
97-
/// Note that F# uses whitespace indentation-aware syntax, similar to languages like Python or Ruby.
119+
/// Note that F# uses whitespace indentation-aware syntax, similar to languages like Python.
98120
letsampleFunction3 x=
99121
if x<100.0then
100122
2.0*x*x- x/5.0+3.0
@@ -192,6 +214,78 @@ module Tuples =
192214
printfn"Struct Tuple:%A\nReference tuple made from the Struct Tuple:%A" sampleStructTuple(sampleStructTuple|> convertFromStructTuple)
193215

194216

217+
/// The F# pipe operators ('|>', '<|', etc.) and F# composition operators ('>>', '<<')
218+
/// are used extensively when processing data. These operators are themselves functions
219+
/// which make use of Partial Application.
220+
///
221+
/// To learn more about these operators, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#function-composition-and-pipelining
222+
/// To learn more about Partial Application, see: https://docs.microsoft.com/en-us/dotnet/articles/fsharp/language-reference/functions/#partial-application-of-arguments
223+
modulePipelinesAndComposition=
224+
225+
/// Squares a value.
226+
letsquare x= x* x
227+
228+
/// Adds 1 to a value.
229+
letaddOne x= x+1
230+
231+
/// Tests if an integer value is odd via modulo.
232+
letisOdd x= x%2<>0
233+
234+
/// A list of 5 numbers. More on lists later.
235+
letnumbers=[1;2;3;4;5]
236+
237+
/// Given a list of integers, it filters out the even numbers,
238+
/// squares the resulting odds, and adds 1 to the squared odds.
239+
letsquareOddValuesAndAddOne values=
240+
letodds= List.filter isOdd values
241+
letsquares= List.map square odds
242+
letresult= List.map addOne squares
243+
result
244+
245+
/// A shorter way to write 'squareOddValuesAndAddOne' is to nest each
246+
/// sub-result into the function calls themselves.
247+
///
248+
/// This makes the function much shorter, but it's difficult to see the
249+
/// order in which the data is processed.
250+
letsquareOddValuesAndAddOneNested values=
251+
List.map addOne(List.map square(List.filter isOdd values))
252+
253+
/// A preferred way to write 'squareOddValuesAndAddOne' is to use F# pipe operators.
254+
/// This allows you to avoid creating intermediate results, but is much more readable
255+
/// than nesting function calls like 'squareOddValuesAndAddOneNested'
256+
letsquareOddValuesAndAddOnePipeline values=
257+
values
258+
|> List.filter isOdd
259+
|> List.map square
260+
|> List.map addOne
261+
262+
/// You can shorten 'squareOddValuesAndAddOnePipeline' by moving the second `List.map` call
263+
/// into the first, using a Lambda Function.
264+
///
265+
/// Note that pipelines are also being used inside the lambda function. F# pipe operators
266+
/// can be used for single values as well. This makes them very powerful for processing data.
267+
letsquareOddValuesAndAddOneShorterPipeline values=
268+
values
269+
|> List.filter isOdd
270+
|> List.map(fun x-> x|> square|> addOne)
271+
272+
/// Lastly, you can eliminate the need to explicitly take 'values' in as a parameter by using '>>'
273+
/// to compose the two core operations: filtering out even numbers, then squaring and adding one.
274+
/// Likewise, the 'fun x -> ...' bit of the lambda expression is also not needed, because 'x' is simply
275+
/// being defined in that scope so that it can be passed to a functional pipeline. Thus, '>>' can be used
276+
/// there as well.
277+
///
278+
/// The result of 'squareOddValuesAndAddOneComposition' is itself another function which takes a
279+
/// list of integers as its input. If you execute 'squareOddValuesAndAddOneComposition' with a list
280+
/// of integers, you'll notice that it produces the same results as previous functions.
281+
///
282+
/// This is using what is known as function composition. This is possible because functions in F#
283+
/// use Partial Application and the input and output types of each data processing operation match
284+
/// the signatures of the functions we're using.
285+
letsquareOddValuesAndAddOneComposition=
286+
List.filter isOdd>> List.map(square>> addOne)
287+
288+
195289
/// Lists are ordered, immutable, singly-linked lists. They are eager in their evaluation.
196290
///
197291
/// This module shows various ways to generate lists and process lists with some functions
@@ -203,9 +297,16 @@ module Lists =
203297
/// Lists are defined using [ ... ]. This is an empty list.
204298
letlist1=[]
205299

206-
/// This is a list with 3 elements. ';' is used to separate elements.
300+
/// This is a list with 3 elements. ';' is used to separate elements on the same line.
207301
letlist2=[1;2;3]
208302

303+
/// You can also separate elements by placing them on their own lines.
304+
letlist3=[
305+
1
306+
2
307+
3
308+
]
309+
209310
/// This is a list of integers from 1 to 1000
210311
letnumberList=[1..1000]
211312

@@ -706,7 +807,7 @@ module UnitsOfMeasure =
706807
openMicrosoft.FSharp.Data.UnitSystems.SI.UnitNames
707808

708809
/// Define a unitized constant
709-
letsampelValue1=1600.0<meter>
810+
letsampleValue1=1600.0<meter>
710811

711812
/// Next, define a new unit type
712813
[<Measure>]
@@ -721,7 +822,7 @@ module UnitsOfMeasure =
721822
letsampleValue3= sampleValue2* mile.asMeter
722823

723824
// Values using Units of Measure can be used just like the primitive numeric type for things like printing.
724-
printfn"After a%f race I would walk%f miles which would be%f meters"sampelValue1 sampleValue2 sampleValue3
825+
printfn"After a%f race I would walk%f miles which would be%f meters"sampleValue1 sampleValue2 sampleValue3
725826

726827

727828
/// Classes are a way of defining new object types in F#, and support standard Object-oriented constructs.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp