├── .gitignore
├── LICENSE
├── README.md
├── build
└── _.mez
├── media
└── heading.PNG
└── src
├── _.sln
└── _
├── _.mproj
├── _.pq
└── _.query.pq
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PowerQueryFunctional
2 | Power Query utility library with a functional twist
3 |
4 | 
5 |
6 | ## Quickstart
7 | This module uses the extensibility provided by [Data Connectors](https://github.com/Microsoft/DataConnectors), so in order to use it you have to:
8 | 1. Create a `[My Documents]\Microsoft Power BI Desktop\Custom Connectors` directory
9 | 2. Enable the **Custom data connectors** preview feature in Power BI Desktop (under *File | Options and settings | Custom data connectors*)
10 | 3. Copy the the contents of `/build` folder with all the *.mez files into the above folder
11 | 4. Restart Power BI Desktop
12 |
13 |
14 | ## For developers
15 | In order to extend the modules
16 | 1. Install the [Power Query SDK](https://aka.ms/powerquerysdk) from the Visual Studio Marketplace
17 | 2. Edit the existing `Data Connector Projects` or *.pq files
18 | 3. Build the solution
19 | The deployable *.mez files will be located in the Debug folder of each module under `/src`. The Relese configuration of the build will copy these files into the `/build` folder.
20 |
21 | # Functions
22 | For additional examples and explanations, please refer to the embeded documentation of each of the functions.
23 | ## _.Identity
24 | A function that does nothing but return the parameter supplied to it. Good as a default or placeholder function.
25 |
26 | `:: a -> a`
27 |
28 | ## _.Const
29 | Return a function which always returns a given value.
30 |
31 | `a -> b -> a`
32 |
33 | ## _.Flip
34 | Reverse the order of arguments to a function of arity 2.
35 |
36 | `:: ((a, b) -> c) -> ((b, a) -> c)`
37 |
38 | ## _.Compose
39 | Perform a right-to-left composition across a list of functions.
40 |
41 | `:: ((y -> z), (x -> y), ..., (a -> b)) -> a -> z`
42 |
43 | ## _.Pipe
44 | Perform a left-to-right composition across a list of functions.
45 |
46 | `:: ((a -> b), (b -> c), ..., (y -> z)) -> a -> z`
47 |
48 | # _.Of
49 | Return a single item array containing the passed value.
50 |
51 | `:: a -> [a]`
52 |
53 | ## _.Partial
54 | Takes a function f and a list of arguments, and returns a function g. When applied, g returns the result of applying f to the arguments provided initially followed by the argument list provided to g.
55 |
56 | `:: ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> ([d, e, f, ..., n] -> x)`
57 |
58 | ## _.Partial1 =
59 | Similar to _.Partial but instead of returning a function expecting a list of remaining arguments, provides a function expecting a final single argument in order to fully apply the initial function.
60 |
61 | `:: ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> (n -> x)`
62 |
63 | ## _.PartialRight
64 | Takes a function f and a list of arguments, and returns a function g. When applied, g returns the result of applying f to the arguments provided to g followed by the argument list provided initially.
65 |
66 | `:: ((a, b, c, ..., n) -> x) -> [d, e, f, ..., n] -> ([a, b, c, ...] -> x)`
67 |
68 | ## _.PartialRight1
69 | Similar to PartialRight however accepts a single, final argument in order to fully apply the intial function.
70 |
71 | `:: ((a, b, c, ..., n) -> x) -> d, e, f, ..., n] -> (a -> x)`
72 |
73 | ## _.Curry =
74 | Curry a function so that arguments are supplied one at a time up until the specified arity is met at which point the original function will be invoked.
75 |
eg.Curry((a, b, c) => x) = (a) => (b) => (c) => x
76 |
77 | `:: number (* -> a) -> (* -> a)`
78 |
79 | ## _.Foldl
80 | Perform a left-associative reduction over a list.
81 |
82 | `:: (a b -> a) a -> [b] -> a`
83 |
84 | ## _.Foldr
85 | Perform a right-associative reduction over a list.
86 |
87 | `:: (a b -> b) -> b -> [a] -> b`
88 |
89 | ## _.Map
90 | Apply a transform to all elements of a list.
91 |
92 | `(a -> b) -> [a] -> [b]`
93 |
94 | ## _.Filter
95 | Evaluate elements of a list against a predicate, returning a new list of the items which evaluated to true.
96 |
97 | `:: (a -> Boolean) -> [a] -> [a]`
98 |
99 | ## _.Combine
100 | Given two lists, create a new list containing the result of appending b to a.
101 |
102 | `:: [a] [a] -> [a]`
103 |
104 | ## _.Prepend
105 | Add a single element to the head of a list and return a new list containing the merged result.
106 |
107 | `:: a -> [a] -> [a]`
108 |
109 | ## _.ChainOperations
110 | Provide the ability to chain sequences of internal table, record and list operations.
111 | The internal transform functions all take the object being transformed as parameter 0. To remove the need to assign intermediate variables this lifts that argument to be within a higher-order function allowing a sequence of operations to be performed. This sequence is defined as a list of lists, with element 0 containing the transform function and elements 1..n containing the arguments 1..n for that transform.
112 |
113 | `[(a -> b, x, y, ..n), (b -> c, x, y, ..n),...] -> a -> z`
114 | ```javascript
115 | TransformDummyTable = _.ChainOperations({
116 | {Table.SelectColumns, {"Col1", "Col2"}},
117 | {Table.RenameColumns, {"Col1", "Id"}},
118 | {Table.RenameColumns, {"Col2", "Alfa"}}
119 | })(
120 | #table({"Col1","Col2","Col3"},
121 | {{1,"A","B"},
122 | {2,"C","D"}})
123 | )
124 | ```
125 |
126 | ## References
127 |
128 | The M functions used in this library have been inspired from the following repository
129 | * [m-tools](https://github.com/acaprojects/m-tools)
--------------------------------------------------------------------------------
/build/_.mez:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/PowerQueryFunctional/a0c727286aff0ea2df965f5b502d50d5835063d0/build/_.mez
--------------------------------------------------------------------------------
/media/heading.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hugoberry/PowerQueryFunctional/a0c727286aff0ea2df965f5b502d50d5835063d0/media/heading.PNG
--------------------------------------------------------------------------------
/src/_.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26730.16
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{4DF76451-A46A-4C0B-BE03-459FAAFA07E6}") = "_", "_\_.mproj", "{9E98BEAF-FCE2-46E9-B043-98BEBCE51851}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Release|x86 = Release|x86
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {9E98BEAF-FCE2-46E9-B043-98BEBCE51851}.Debug|x86.ActiveCfg = Debug|x86
15 | {9E98BEAF-FCE2-46E9-B043-98BEBCE51851}.Debug|x86.Build.0 = Debug|x86
16 | {9E98BEAF-FCE2-46E9-B043-98BEBCE51851}.Release|x86.ActiveCfg = Release|x86
17 | {9E98BEAF-FCE2-46E9-B043-98BEBCE51851}.Release|x86.Build.0 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {96555B05-6087-494E-A1AD-6B0FB67C2373}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/_/_.mproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Debug
4 | 2.0
5 |
6 |
7 | Exe
8 | MyRootNamespace
9 | MyAssemblyName
10 | False
11 | False
12 | False
13 | False
14 | False
15 | False
16 | False
17 | False
18 | False
19 | False
20 | 1000
21 | Yes
22 | _
23 |
24 |
25 | false
26 |
27 | bin\Debug\
28 |
29 |
30 | false
31 | ..\..\build\
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | Code
42 |
43 |
44 | Code
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/src/_/_.pq:
--------------------------------------------------------------------------------
1 | section _;
2 |
3 | _Compose =
4 | Document(
5 | "_Compose",
6 | "Right-to-left composition of a pair of unary functions
7 |
:: (b -> c) (a -> b) -> a -> c",
8 | null,
9 | (f, g) => (x) => f(g(x))
10 | );
11 |
12 | shared _.Identity =
13 | Document(
14 | "_.Identity",
15 | "A function that does nothing but return the parameter supplied to it. Good as a default or placeholder function.
16 |
:: a -> a",
17 | {[ Description = "Identity of the sine function", Code="_.Identity(Number.Sin)(0)", Result="0"]},
18 | (a) => a
19 | );
20 |
21 | shared _.Const =
22 | Document(
23 | "_.Const",
24 | "Return a function which always returns a given value.
25 |
a -> b -> a",
26 | {[ Description = "Always return digits", Code="_.Const({0..9})", Result="{0..9}"]},
27 | (a) => (b) => a
28 | );
29 |
30 | shared _.Flip =
31 | Document(
32 | "_.Flip",
33 | "Reverse the order of arguments to a function of arity 2.
34 |
:: ((a, b) -> c) -> ((b, a) -> c)",
35 | {[ Description = "Flip the divident with divisor", Code="_.Flip(Number.IntegerDivide)(1,2)", Result="2"]},
36 | (f) => (a, b) => f(b, a)
37 | );
38 |
39 | shared _.Compose =
40 | Document(
41 | "_.Compose",
42 | "Perform a right-to-left composition across a list of functions.
43 |
:: ((y -> z), (x -> y), ..., (a -> b)) -> a -> z",
44 | {[ Description = "Compose sin(cos(1))", Code="_.Compose({Number.Sin,Number.Cos})(1)", Result="0.51439525852354917"]},
45 | _.Foldr(_Compose, _.Identity)
46 | );
47 |
48 | shared _.Pipe =
49 | Document(
50 | "_.Pipe",
51 | "Perform a left-to-right composition across a list of functions.
52 |
:: ((a -> b), (b -> c), ..., (y -> z)) -> a -> z",
53 | {[ Description = "Compose cos(sin(1))", Code="_.Pipe({Number.Sin,Number.Cos})(1)", Result="0.66636674539288054"]},
54 | _.Foldl(_.Flip(_Compose), _.Identity)
55 | );
56 |
57 | shared _.Of =
58 | Document(
59 | "_.Of",
60 | "Return a single item array containing the passed value.
61 |
:: a -> [a]",
62 | {[ Description = "Return 1 as a list {1}", Code="_.Of(1)", Result="{1}"]},
63 | (a) => {a}
64 | );
65 |
66 | shared _.Partial =
67 | Document(
68 | "_.Partial",
69 | "Takes a function f and a list of arguments, and returns a function g. When applied, g returns the result of applying f to the arguments provided initially followed by the argument list provided to g.
70 |
:: ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> ([d, e, f, ..., n] -> x)",
71 | {[ Description = "Double a number through partial application",
72 | Code="double = _.Partial(Value.Multily,{2}),
73 |
six = mdouble({3})", Result="6"]},
74 | (f, a) => (b) => Function.Invoke(f, a & b)
75 | );
76 |
77 | shared _.Partial1 =
78 | Document(
79 | "_.Partial1",
80 | "Similar to _.Partial but instead of returning a function expecting a list of remaining arguments, provides a function expecting a final single argument in order to fully apply the initial function.
81 |
:: ((a, b, c, ..., n) -> x) -> [a, b, c, ...] -> (n -> x)",
82 | {[ Description = "", Code="double = _.Partial1(Value.Multily,{2}),
83 |
six = mdouble(3)", Result="6"]},
84 | (f, a) => _Compose(_.Partial(f, a), _.Of)
85 | );
86 |
87 | shared _.PartialRight =
88 | Document(
89 | "_.PartialRight",
90 | "Takes a function f and a list of arguments, and returns a function g. When applied, g returns the result of applying f to the arguments provided to g followed by the argument list provided initially.
91 |
:: ((a, b, c, ..., n) -> x) -> [d, e, f, ..., n] -> ([a, b, c, ...] -> x)",
92 | {[ Description = "Double the numbers of a list", Code="double = _.PartialRight(List.Transform,{each _*2})
93 |
digits = double({{0..9}})", Result="List=0,2,4,..18"]},
94 | (f, a) => (b) => Function.Invoke(f, b & a)
95 | );
96 |
97 | shared _.PartialRight1 =
98 | Document(
99 | "_.PartialRight1",
100 | "Similar to PartialRight however accepts a single, final argument in order to fully apply the intial function.
101 |
:: ((a, b, c, ..., n) -> x) -> d, e, f, ..., n] -> (a -> x)",
102 | {[ Description = "", Code="double = _.PartialRight1(List.Transform,{each _*2})
103 |
digits = double({0..9})", Result="List=0,2,4,..18"]},
104 | (f, a) => _Compose(_.PartialRight(f, a), _.Of)
105 | );
106 |
107 | shared _.Curry =
108 | Document(
109 | "_.Curry",
110 | "Curry a function so that arguments are supplied one at a time up until the specified arity is met at which point the original function will be invoked.
111 |
eg.Curry(3, (a, b, c) => x) = (a) => (b) => (c) => x
112 |
:: number (* -> a) -> (* -> a)",
113 | {[ Description = "Curry a function with arity 4", Code="_.Curry((x,y,z,w)=>{x,y,z,w})(1)(2)(3)(4)", Result="{1,2,3,4}"]},
114 | (f) =>
115 | let
116 | arity = Record.FieldCount(Type.FunctionParameters(Value.Type(f))),
117 | Apply = (args) =>
118 | if List.Count(args) >= arity then Function.Invoke(f, args)
119 | else (x) => @Apply(args & _.Of(x))
120 | in
121 | Apply({})
122 | );
123 |
124 | shared _.Foldl =
125 | Document(
126 | "_.Foldl",
127 | "Perform a left-associative reduction over a list.
128 |
:: (a b -> a) a -> [b] -> a",
129 | {[ Description = "", Code="_.Foldl((s,c)=>{s&{c}},{0})({1..3})", Result="{{{{0},1},2},3}"]},
130 | (fn, seed) => (list) => List.Accumulate(list, seed, fn)
131 | );
132 |
133 | shared _.Foldr =
134 | Document(
135 | "_.Foldr",
136 | "Perform a right-associative reduction over a list.
137 |
:: (a b -> b) -> b -> [a] -> b",
138 | {[ Description = "", Code="_.Foldr((s,c)=>{{s}&c},{0})({1..3})", Result="{0,{1,{2,{3}}}}"]},
139 | (fn, seed) => (list) =>
140 | if List.IsEmpty(list) then seed
141 | else
142 | let
143 | x = List.Last(list),
144 | xs = List.RemoveLastN(list, 1)
145 | in
146 | fn(@_.Foldr(fn, x)(xs), seed)
147 | );
148 |
149 | shared _.Map =
150 | Document(
151 | "_.Map",
152 | "Apply a transform to all elements of a list.
153 |
(a -> b) -> [a] -> [b]",
154 | {[ Description = "Apply a function to a list of integers", Code="= _.Map(Number.Factorial)({1..5})", Result="{1,2,6,24,120}"]},
155 | (fn) => (list) => List.Transform(list, fn)
156 | );
157 |
158 | shared _.Filter =
159 | Document(
160 | "_.Filter",
161 | "Evaluate elements of a list against a predicate, returning a new list of the items which evaluated to true.
162 |
:: (a -> Boolean) -> [a] -> [a]",
163 | {[ Description = "Enumerate Odd numbers in list {0..9}", Code="= _.Filter(Number.IsOdd)({0..9})", Result="{1,3,5,7,9}"]},
164 | (fn) => (list) => List.Select(list, fn)
165 | );
166 |
167 | shared _.Combine =
168 | Document(
169 | "_.Combine",
170 | "Given two lists, create a new list containing the result of appending b to a.
171 |
:: [a] [a] -> [a]",
172 | {[ Description = "Concatenate two lists", Code="_.Combine({1,2},{3,4})", Result="{1,2,3,4}"]},
173 | (a, b) => a & b
174 | );
175 | shared _.Append =
176 | Document(
177 | "_.Append",
178 | "Add a single element to the tail of a list and return a new list containing the merged result.
179 |
:: a -> [a] -> [a]",
180 | {[ Description = "Append 2 to a list of {4}", Code="_.Append(2)({4})", Result="{4,2}"]},
181 | (a) => (list) => list & _.Of(a)
182 | );
183 |
184 | shared _.Prepend =
185 | Document(
186 | "_.Prepend",
187 | "Add a single element to the head of a list and return a new list containing the merged result.
188 |
:: a -> [a] -> [a]",
189 | {[ Description = "Prepend 2 to a list of {4}", Code="_.Prepend(2)({4})", Result="{2,4}"]},
190 | (a) => (list) => _.Of(a) & list
191 | );
192 |
193 | shared _.ChainOperations =
194 | Document(
195 | "_.ChainOperations",
196 | "Provide the ability to chain sequences of internal table, record and list operations.
197 |
The internal transform functions all take the object being transformed as parameter 0. To remove the need to assign intermediate variables this lifts that argument to be within a higher-order function allowing a sequence of operations to be performed. This sequence is defined as a list of lists, with element 0 containing the transform function and elements 1..n containing the arguments 1..n for that transform.
198 |
:: [(a -> b, x, y, ..n), (b -> c, x, y, ..n),...] -> a -> z",
199 | {[ Description = "Apply multiple table transformations", Code="TransformDummyTable = _.ChainOperations({
200 | {Table.SelectColumns, {""Col1"", ""Col2""}},
201 | {Table.RenameColumns, {""Col1"", ""Id""}},
202 | {Table.RenameColumns, {""Col2"", ""Alfa""}}
203 | })(#table({""Col1"",""Col2"",""Col3""},{{1,""A"",""B""},{2,""C"",""D""}}))", Result="function"]},
204 |
205 | let
206 | Transform = (t) =>
207 | let
208 | f = List.First(t),
209 | args = List.Skip(t)
210 | in
211 | _.PartialRight1(f, args)
212 | in
213 | _Compose(_.Pipe, _.Map(Transform))
214 | );
215 |
216 | shared _.IChain =
217 | Document(
218 | "_.IChain",
219 | "Similar to _.ChainOperations apart from the order of the function arguments: The object to be transformed comes before the list of chain operations.
220 |
The internal transform functions all take the object being transformed as parameter 0. To remove the need to assign intermediate variables this lifts that argument to be within a higher-order function allowing a sequence of operations to be performed. This sequence is defined as a list of lists, with element 0 containing the transform function and elements 1..n containing the arguments 1..n for that transform.
221 |
:: [(a -> b, x, y, ..n), (b -> c, x, y, ..n),...] -> a -> z",
222 | {[ Description = "Divide first, then raise by power", Code="_.IChain(10, { {each _/2}, {Number.Power, 3} } )", Result="125"]},
223 |
224 | (x, operations) =>
225 | let
226 | IChain = _.ChainOperations(operations)
227 | in
228 | IChain(x)
229 | );
230 |
231 | /////////////////////////
232 | // Dependencies //
233 | /////////////////////////
234 |
235 | Document = (name as text, description as text, valueOrExample as any, optional valueIfExample as any) =>
236 | let
237 | value = if valueIfExample is null then valueOrExample else valueIfExample,
238 | examples = if valueIfExample is null then {} else valueOrExample
239 | in
240 | Value.ReplaceType(value, Value.Type(value) meta [
241 | Documentation.Name = name,
242 | Documentation.Description = description,
243 | Documentation.Examples = examples
244 | ]);
--------------------------------------------------------------------------------
/src/_/_.query.pq:
--------------------------------------------------------------------------------
1 | // Use this file to write queries to test your data connector
2 | let
3 | result = _.IChain(10, { {each _/2}, {Number.Power, 3} })
4 | in
5 | result
--------------------------------------------------------------------------------