Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Cfml features modern coding into the box 2018

62 views

Published on

Daniel Fredericks

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Cfml features modern coding into the box 2018

  1. 1. CFML Features for More Modern Coding Download This Presentation: Queries and Closures and loops…OH MY! Download Original Presentation: http://bit.ly/2cIjXuI
  2. 2. CFML Features for More Modern Coding Queries and Closures and loops…OH MY! Dan Fredericks fmdano@gmail.com @fmdano74 http://www.meetup.com/nvcfug/ Download This Presentation: Download Original Presentation: http://bit.ly/2cIjXuI
  3. 3. What this Presentation will cover: • CFScript Support • QueryExecute() Function • Member Functions • Elvis Function • Closures • Map, Reduce, Filter, Each • First Class Functions and Callbacks • CF 2016 Special Download Original Presentation: http://bit.ly/2cIjXuI
  4. 4. QueryExecute • CFQUERY has been the staple to query a database since day 1 • There have been a few attempts to query the database using script • Here is the latest alternative for script based syntax Syntax: QueryExecute( sql_stmt, queryParams, queryOptions );
  5. 5. QueryExecute Old Script Syntax <cfscript> q = new com.adobe.coldfusion.query(); q.setDatasource("cfartgallery"); q.setSQL("select * from art where artname like :search or description like :search"); q.addParam(name="search",value="%e%",cfsqltype="cf_sql_varchar"); r = q.execute(); </cfscript>
  6. 6. QueryExecute CFScript.me Script Syntax cfquery( ) { writeOutput("select id, firstname, lastname from userTable where lastname = 'Jones'"); } Note: queryExecute() is the preferred syntax but this syntax is easier to convert generically This syntax comes from using CFScript.me to convert tag syntax to one form of script syntax
  7. 7. QueryExecute New Script Syntax queryExecute( sql_stmt, queryParam, queryOptions); Numbers = (1) queryExecute(“ SELECT * FROM art WHERE artname like ‘%this%’ ORDER BY id“, (2) {type={value=“number”, cfsqltype=“cf_sql_varchar”}}, or {value=“color”}, (3) {datasource = “scratch_mssql”} );
  8. 8. QueryExecute • This function simplifies the query execution in the CFScript block. • This function lets you pass unnamed parameters to the query. Use '?' (question mark) as the place-holder for the parameters. The values to the parameters should be passed as an array toparams. • If there are any Query parameters, they must be passed as the second argument of the function. It can be either a struct or an array. • If you need to provide additional attribute as a Query parameter (like CFSQLType, list, and separator), you can pass these as struct against that column name. • The Query and datasource properties will be passed as the third argument.
  9. 9. QueryExecute From Adobe Help <cfset qoptions = {result="myresult", datasource="artGallery"}> <cfset myquery = QueryExecute("select * from art where ARTID < 5", [] ,qoptions)> <cfset myquery1 = QueryExecute("select * from art where ARTID < ?", [4] ,qoptions)> <cfset myquery2 = QueryExecute("select * from art where ARTID < :artid and artistid=:aid ", {artid={value=100}, aid=2} ,qoptions)> Note: queryExecute is just a function so can be used in tags as well:
  10. 10. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Tag Syntax <cfquery name=“qryResult”> SELECT * FROM Employees </cfquery> Script Syntax qryResult = queryExecute( "SELECT * FROM Employees“ );
  11. 11. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Parameters using Structure Syntax Tag Syntax <cfset country = “USA” /> <cfset empid = 1 /> <cfquery name=“qryResult”> SELECT * FROM Employees WHERE empid = #empID# AND country = #country# </cfquery> ** Should use cfqueryparm Script Syntax (Parameters using Struct) qryResult = queryExecute(“ SELECT * FROM Employees WHERE empid = :empid AND country = :country", {country="USA", empid=1} );
  12. 12. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Parameters using Array Syntax Tag Syntax <cfset country = “USA” /> <cfset empid = 1 /> <cfquery name=“qryResult”> SELECT * FROM Employees WHERE empid = #empID# AND country = #country# </cfquery> ** Should use cfqueryparm Script Syntax (Parameters using Array) qryResult = queryExecute(“ SELECT * FROM Employees WHERE empid = ? AND country = ?", [1, “usa”] );
  13. 13. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Parameters using Structs of Structs Tag Syntax <cfset country = “USA” /> <cfset empid = 1 /> <cfquery name=“qryResult”> SELECT * FROM Employees WHERE empid = #empID# AND country = #country# </cfquery> ** Should use cfqueryparm Script Syntax qryResult =queryExecute(“ SELECT * FROM Employees WHERE empid = :empid AND country = :country", {country={value="USA",cfsqltype="cf_sql_varchar"}, empid={value=1, cfsqltype="cf_sql_integer"} } );
  14. 14. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Tag Syntax (Specify a datasource) <cfquery name=“qryResult” datasource = “myDatasourceName”> SELECT * FROM Employees </cfquery> Script Syntax (Specify a datasource) qryResult = queryExecute(“ SELECT * FROM Employees", {}, {datasource= "myDataSourceName"} );
  15. 15. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Tag Syntax (query with a subquery) <cffunction name=“getEqMfg” returntype=“query” access=“public”> <cfargument name=“dc” cfsqltype=“string” required=“true”> <cfquery name=“ml” datasource=“myDSN”> Select name, mfgCode, country From mfgdetails_tbl Where mfgcode in ( Select mfgCode From mfg2devices_tbl Where deviceCode = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.dc#“ maxlength=“5”> ) Order By country, name </cfquery> <cfreturn ml > </cffunction> Script Syntax (query with a subquery) public query function getEqMfg(required string dc){ var ml = queryExecute(“ Select name, mfgCode, country From mfgdetails_tbl Where mfgcode in ( Select mfgCode From mfg2devices_tbl Where deviceCode = :dcp ) Order By country, name", {dcp={value="dc",cfsqltype="CF_SQL_VARCHAR", maxlength=5 }}, {datasource = “myDSN”} ); return ml; }
  16. 16. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Tag Syntax (Return a number/count or maxRows) <cfquery name=“dsc”> Select count(*) as qty From generic_view” </cfquery> <cfquery name=“sc” maxrows=“#rc#”> Select specialtyname, qty From generic_view Order by qty DESC, specialtyname </cfquey> Script Syntax (Return a number/count or maxRows) public numeric function getSpecialtyCount(){ var dsc = queryExecute("Select Count(*) as qty From specialtycategorycount_view"); return dsc.qty; } query function getSpecialtyCodeChartData(required numeric rc=99){ var sc = queryExecute("Select specialtyname, qty From specialtycategorycount_view Order by qty DESC, specialtyname", {}, {maxrows = "rc"}); return sc; }
  17. 17. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); If you want to add if logic into your query (just example logic): Savecontent variable=“sql”{ SELECT * FROM words <cfif structKeyExists(URL, "type")> WHERE type = :type <cfset params = {type={value=URL.type, cfsqltype="CF_SQL_VARCHAR"}}> <cfelse> <cfset params = {}> </cfif> ORDER BY id } Once you add the sql statement into a saveContent/variable, just add the variable name into the queryExecute statement: numbers = queryExecute(sql, params, {datasource=“dsnName”});
  18. 18. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); public query function select ( struct criteria={} ) { var SQLs = ‘’; var SQLw = ‘’; var SQLParams = {}; SQLs = "SELECT id, firstName, lastName, address1, city, state, zip, phoneNbr, email, active FROM userTable"; SQLw = structIsEmpty( criteria ) ? "WHERE 1=0 " : "WHERE 1=1 "; if ( structKeyExists( criteria, "lastName" ) ) { SQLw &= "AND lastName = :lastName "; SQLParams.append( { lastName={ value=criteria.lastName, cfsqltype="cf_sql_varchar", list=true } } ); } if ( structKeyExists( criteria, "state" ) ) { SQLw &= "AND state in (:state) "; SQLParams.append( { state={ value=criteria.state, cfsqltype="cf_sql_varchar", list=true } } ); } SQLs &= SQLw & " ORDER BY state DESC, lastName DESC"; return queryExecute( SQLs, SQLParams, { datasource=myDatasource } ); } }
  19. 19. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Different Select QueryExecute Syntax (borrowed from CFVonner) public query function getAllBeers () { return queryExecute( "SELECT be.id ,be.breweryId ,be.name ,br.name AS breweryName ,be.type ,be.abv ,be.ibu FROM Beer be LEFT JOIN Brewery br ON be.breweryId = br.id ORDER BY be.name ASC" ); // queryExecute equivalent to <cfquery> } public query function getBeer ( required numeric id ) { return queryExecute( "SELECT id ,breweryId ,name ,type ,abv ,ibu FROM Beer WHERE id = :id", { id = { value = arguments.id, cfsqltype = 'integer' } } // equivalent to <cfqueryparam> ); }
  20. 20. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Insert QueryExecute Syntax (borrowed from CFVonner) var result = ''; queryExecute( "INSERT INTO Beer ( name, breweryId, type, abv, ibu ) VALUES ( :name, :breweryId, :type, :abv, :ibu )", { name = { value = arguments.name, null = hs.isEmptyString( arguments.name ), cfsqltype = 'varchar' }, breweryId = { value = arguments.breweryId, null = hs.isEmptyString( arguments.breweryId ), cfsqltype = 'integer' }, type = { value = arguments.type, null = hs.isEmptyString( arguments.type ), cfsqltype = 'varchar' }, abv = { value = arguments.abv, cfsqltype = 'decimal' }, ibu = { value = arguments.ibu, cfsqltype = 'decimal' } }, { result = 'result'} );
  21. 21. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Update QueryExecute Syntax (borrowed from CFVonner) queryExecute( "UPDATE Beer SET name = :name ,breweryId = :breweryId ,type = :type ,abv = :abv ,ibu = :ibu WHERE id = :id", { id = { value = arguments.id, cfsqltype = 'integer'},name = { value = arguments.name, null = hs.isEmptyString( arguments.name ), cfsqltype = 'varchar' }, breweryId = { value = arguments.breweryId, null = hs.isEmptyString( arguments.breweryId ), cfsqltype = 'integer' },type = { value = arguments.type, null = hs.isEmptyString( arguments.type ), cfsqltype = 'varchar' }, abv = { value = arguments.abv, cfsqltype = 'decimal' }, ibu = { value = arguments.ibu, cfsqltype = 'decimal' } } );
  22. 22. QueryExecute queryExecute( sql_stmt, queryParam, queryOptions); Delete QueryExecute Syntax (borrowed from CFVonner) queryExecute( "DELETE FROM Beer WHERE id = :id", { id={ value=arguments.id, cfsqltype='integer' } } );
  23. 23. QueryExecute For Review: queryExecute( sql_stmt, queryParam, queryOptions); Numbers = (1) queryExecute(“ SELECT * FROM art WHERE artname like ‘%this%’ ORDER BY id“, (2) {type={value=“number”, cfsqltype=“cf_sql_varchar”}}, or {value=“color”}, (3) {datasource = “scratch_mssql”} );
  24. 24. QueryExecute queryExecute: https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion- functions/functions-m-r/queryexecute.html CFDocs.org: http://cfdocs.org/queryexecute Query options: http://stackoverflow.com/questions/26296467/what-are-the-options-for- queryoptions-in-the-queryexecute-function Get rid of cfqueryparam: http://blog.adamcameron.me/2014/03/querycfc-queryexecute- have-good-feature.html queryExecute:http://blog.adamcameron.me/2014/02/coldfusion-11-queryexecute.html Check out cfuser examples: http://www.cfuser.com/more-queryexecute-examples/ Cfuser: http://www.cfuser.com/more-queryexecute-examples/ CFVonner github examples: https://github.com/cfvonner/Intro-to-MVC-ColdFusion
  25. 25. Closures • A Closure is a function which binds variable references at declaration time not at use-time • Callbacks are not Closures (inline callbacks are) • That inner function has access to the var scope of the function it was defined from. This is what a closure is. It knows about its origin and it doesn't forget. It will always be tied to that same parent var scope.
  26. 26. Closures From StackOverflow https://softwareengineering.stackexchange.com/questions/285941/why-would-a-program-use-a-closure Why write a closure? What specific task would a programmer be performing that might be best served by a closure? The purpose of closures is simply to preserve state; hence the name closure - it closes over state. Closures allow you to instantiate functions. Where closures really shine over other constructs is when using higher-order functions, when you actually need to communicate state, and you can make it a one-liner… OO is about data abstraction, and closures are the way to perform data abstraction.
  27. 27. Closures From StackOverflow Why write a closure? What specific task would a programmer be performing that might be best served by a closure? Continued… A couple of other examples: Sorting Most sort functions operate by comparing pairs of objects. Some comparison technique is needed. Restricting the comparison to a specific operator means a rather inflexible sort. A much better approach is to receive a comparison function as an argument to the sort function. Sometimes a stateless comparison function works fine (e.g., sorting a list of numbers or names), but what if the comparison needs state? Random numbers The original rand() took no arguments. Pseudorandom number generators need state. Some (e.g., Mersenne Twister) need lots of state. Even the simple but terrible rand() needed state. Read a math journal paper on a new random number generator and you'll inevitably see global variables. That's nice for the developers of the technique, not so nice for the callers. Encapsulating that state in a structure and passing the structure to the random number generator is one way around the global data problem. This is the approach used in many non- OO languages to making a random number generator reentrant. A closure hides that state from the caller. A closure offers the simple calling sequence of rand() and the reentrancy of encapsulated state.
  28. 28. Closures Example A Classic jQuery Example of Closures: $(function() { var selections = []; // this closure has access to the selections variable $(".niners").click(function() {​ // update the selections variable in the outer function's scope​ selections.push (this.prop("name")); });​ });
  29. 29. Closures javascript example (works in CF also) Function outerFunction() { var a = 3; return function innerFunction(b){ var c = a + b; return c; } } (1) var foo = outerFunction() (2) var result = foo(2); (3) Console.log(result); //5 • We have an outer function with a nested function which accepts a parameter b • (1)When you invoke the outer you get the inner returned later. • (2)Notice the outer function was called but the a still has its value and is used in the return function (innerFunction). • (3)That is why the result Is 5! • http://taha-sh.com/blog/understanding- closures-in-javascript
  30. 30. Closures Example var dwightSalary = (function() { var salary = 60000; function changeBy(amount) { salary += amount; } return { raise: function() { changeBy(5000); }, lower: function() { changeBy(-5000); }, currentAmount: function() { return salary; } }; })(); alert(dwightSalary.currentAmount()); // $60,000 dwightSalary.raise(); alert(dwightSalary.currentAmount()); // $65,000 dwightSalary.lower(); dwightSalary.lower(); alert(dwightSalary.currentAmount()); // $55,000 dwightSalary.changeBy(10000) // TypeError: undefined is not a function
  31. 31. Closures ColdFusion Docs Example: function helloTranslator(String helloWord) { return function(String name) { return "#helloWord#, #name#"; }; } helloInHindi=helloTranslator("Namaste"); helloInFrench=helloTranslator("Bonjour"); writeoutput(helloInHindi("Anna"));  Namaste, Anna writeoutput(helloInFrench("John"));  Bonjour, John • In this case, using closure, two new functions are created. One adds Namaste to the name. And the second one adds Bonjour to the name. • helloInHindi and helloInFrench are closures. They have the same function body; however, store different environments. • The inner function is available for execution after the outer function is returned. The outer function returns the closure • A closure is formed when the inner function is available for execution. Meaning, it is formed when it is defined, not when it is used.
  32. 32. Closures • Ray Camden example (technically is, but more like a callback/inline function) : Data = [“Neil Diamond”, “Depeche Mode”, “The Cure”, “Cher”, “Ace of Base”, “Frank Sinatra”, The Church”]; arraySort(data, function(a,b){ var first = a; var second = b; first = replace(first, “The “, “”); second = replace(second, “The “, “”); return first gt second; }); This code above will order the data array by names excluding THE. Ace of Base, Cher, The Church, The Cure, Depeche Mode, Frank Sinatra, Neil Diamond
  33. 33. Closures ColdFusion built in Functions that use Closures: • CF10 Closure Functions: • ArrayEach, StructEach • ArrayFilter, StructFilter,ListFilter • ArrayFindAt, ArrayFindAllNoCase • CF11 Closure Functions: • isClosure • ArrayReduce, StructReduce, ListReduce • ArrayMap, StructMap, ListMap • CF 2016 added each, map, reduce & filter for Queries
  34. 34. Closures Determines weather a value or expression references a function via a function expression, as opposed to a function statement. isClosure(value) square = function(x) { return x * x; }; writeDump(isClosure(square)); Answer: True square = function(x) { return x * x; }; squared = square(5); writeDump(isClosure(squared)); Answer: False
  35. 35. Closures arrayFindAll ArrayFindAll(array, object) or ArrayFindAll( array, function(arrayElement) { return true|false; } ) Data=[{age:4}, {age:6}, {age:41}]; Answer = arrayFindAll(data, function(item){ return item.age < 10; }); Answer [1,2]
  36. 36. Closures Example from Sean Corfield Don’t look so much at all the details, but compare it to other simple examples of closures in this section, the next section and all the resources. public numeric function createPendingMembershipAndTransaction( numeric amount, numeric rebillRate, any rate, string promocode, any user, any site, string paymentAction = 'Rebilling', any adminUser = 0, string acct_type = "credit_card" ) { return createPendingMembershipAndPartialTransaction( amount, rebillRate, rate, promocode, user, site, paymentAction, adminUser, "sbw", function( string paymentAction, numeric amount, any tx ) { var sbw = this.createSBWTransaction( serviceType = paymentAction == "rebilling" ? "one_click" : lCase( paymentAction ), acctType = acct_type, billId = 0, // we'll update this after the sale transactionId = tx.getId() ); sbw.save(); } ); }
  37. 37. Closures Testbox: https://www.ortussolutions.com/product/testbox • TestBox uses Closures • Since the implementations of the describe() and it() functions are closures, they can contain executable code that is necessary to implement the test. All ColdFusion rules of scoping apply to closures, so please remember them. We recommend always using the variables scope for easy access and distinction. • A test suite begins with a call to our TestBox describe() function with at least two arguments: a title and a closure within the life-cycle method called run(). The title is the name of the suite to register and the function is the block of code that implements the suite. function run() { describe("A suite is a closure", function() { c = new Calculator(); it("and so is a spec", function() { expect( c ).toBeTypeOf( 'component' ); }); }); }
  38. 38. Closures Testbox: https://www.ortussolutions.com/product/testbox • Show Example TestBox code. • Describe – it • Given – when - then describe( “msg", function(){ scenario( "Get similar Orgs", function(){ given( "I have selected a specifc Orgname1", function(){ when( "I run the query …", function(){ then( "the result should be any other Orgs that have similar names", function(){ expect( comOrgsVar.getLikeOrgNames('Orgname1 specific') ).toBeQuery(); }); }); }); }); })
  39. 39. Closures • Some Example code online or resources: • Sesame library inline functions/closures https://github.com/markmandel/Sesame • Underscore.cfc ported from underscore.js https://github.com/russplaysguitar/UnderscoreCF • TestBox gives the ability to use closures http://wiki.coldbox.org/wiki/TestBox.cfm • Adam Tuttle presentation on closures http://fusiongrokker.com/p/closures/#/ • Adam Cameron blog multiple Closure examples http://blog.adamcameron.me/search/label/Closure • JavaScript Closures Explained by Mailing a Package https://medium.freecodecamp.com/javascript-closures-explained-by-mailing-a-package- 4f23e9885039#.y3xfusrpm • Simple Closure example: http://ketanjetty.com/coldfusion/javascript/closures/ • Easy to follow JS Closure Example: https://lawrencebarsanti.wordpress.com/2010/11/09/easy-to-follow-javascript-closure- example/
  40. 40. Closures • Ryan Guill example: https://github.com/ryanguill/emit/blob/master/lib/emit.cfc#L390 • Framework one use of Closures: https://github.com/framework- one/fw1/blob/develop/framework/ioc.cfc#L100-L167 • Framework one example 2: https://github.com/framework- one/fw1/blob/develop/framework/one.cfc#L1166-L1205 • Example from Sean Corfield: https://gist.github.com/seancorfield/86e37a080df62a4c66db4075284de6d8 • Example from Sean Corfield #2: https://gist.github.com/seancorfield/f6521edfb0b10ba406840080df58fff4 • Understanding JS closures: https://medium.com/dailyjs/i-never-understood-javascript-closures- 9663703368e8
  41. 41. Higher Order Functions: Using Map, Filter, Each and Reduce for More Maintainable Code
  42. 42. Map, Reduce, Each, and Filter • The map() functions iterate over the collection (be it a list, array or struct), and returns a new object with an element for each of the ones in the original collection. The callback returns the new element for the new collection, which is derived from the original collection. It is important to note that only the collections values are changed, it will still have the same key/indexes. • So it remaps the original collection • ArrayMap, StructMap, ListMap, (query.map) • The reduce() operation is slightly more complex. Basically it iterates over the collection and from each element of the collection, derives one single value as a result. • ArrayReduce, StructReduce, ListReduce, (query.reduce)
  43. 43. Map and Reduce (and more) • The Filter() function is similar to map and reduce. It will iterate over a given object and return a new object but the original list is unaffected. The callback returns a Boolean to determine if the element is returned in a new object. structEach(circles,function(key,value) { matchednames = arrayfilter(value,function(obj) { return left(obj,1)=='d'; } }); Example shows how to look at a struct and if it begins with a D, return it.
  44. 44. Map and Reduce (and more) • The each() function iterates over a given object and calls a callback for each element. This can be used instead of a loop. letters = ["a","b","c","d"]; arrayEach(letters, function() { writeDump(arguments); }); Struct 1 a struct 1 b struct 1 c struct 1 d
  45. 45. Map and Reduce (and more) •Map() complexData = [ {a: 4}, {a: 18}, {a: 51} ]; newArray = arrayMap( complexData, function(item) { return item.a; }, 0 ); Answer: [4, 18, 51]
  46. 46. Map and Reduce (and more) arrayMap ArrayMap( array, function(item [,index, array]) ) complexData = [{a:4}, {a:18}, {a:51}]; newArray = arrayMap(complexData, function(item){ return item.a; }, 0); Answer [4, 18, 51]
  47. 47. Map and Reduce (and more) • ArrayMap Example ( next few examples from Adam Cameron): dcSports = ["Redskins", "Capitals", "Nationals", "Wizards", "United"]; colourInList = arrayMap(dcSports, function(v,i,a){ return replace(a.toList(), v, ucase(v) ); } ); writeDump([dcSports,colourInList]); Will see an array of dcSports with 7 items each showing the next in the row all caps: REDSKINS,Capitals,Nationals,Wizards,United Redskins,CAPITALS,Nationals,Wizards,United Redskins,Capitals,NATIONALS,Wizards,United
  48. 48. Map and Reduce (and more) • StructMap() original = {"one"={1="redskins"},"two"={2="capitals"},"three"={3="nationals"},"four"={4="wizards"}}; fixed = structMap(original, function(k,v) { return v[v.keyList()]; }); writeDump([ original, fixed]); This just returns the digit as a key and sports team as a value 1 wizards 2 redskins 3 nationals 4 capitals
  49. 49. Map and Reduce (and more) • listMap() dcSports = "Redskins,Capitals,Nationals,Wizards,United"; externalList = ""; reverseSports = listMap( dcSports, function(v,i,l) { var newValue = "#i#:#v.reverse()#"; externalList = externalList.append(newValue); return newValue; }); writeDump([{dcSports=dcSports},{reverseSports=reverseSports},{externalList=externalList}]); This should reverse the dcSports list and show it backwards with index. 1:sniksdeR,2:slatipaC,3:slanoitaN,4:zdraziW,5:detinU
  50. 50. Map and Reduce (and more) colours = queryNew("id,en,mi", "integer,varchar,varchar", [ [1,"red","whero"], [2,"orange","karaka"], [3,"yellow","kowhai"], [4,"green","kakariki"], [5,"blue","kikorangi"], [6,"indigo","poropango"], [10,"violet","papura"] ]); maoriColours = colours.map(function(colour, index, colours){ return {mi=colour.mi}; }, queryNew("mi","varchar")); writeDump(var=maoriColours); Notice that map takes a second argument which Is a second query. This acts as a template for the Remapped query.
  51. 51. Map and Reduce (and more) •Reduce() complexData = [ {a: 4}, {a: 18}, {a: 51} ]; sum = arrayReduce( complexData, function(prev, element) { return prev + element.a; }, 0 ); Answer: 73
  52. 52. Map and Reduce (and more) arrayReduce ArrayReduce( array, function(result, item, [,index, array]) [, initialValue] ) complexData = [{a:4}, {a:18}, {a:51}]; Function reducer(prev, element){ return prev + element.a; } sumOfData = arrayReduce(complexData, reducer, 0); Answer 73
  53. 53. Map and Reduce (and more) • arrayReduce() dcSports = ["Redskins", "Capitals", "Nationals", "Wizards", "United"]; ul = arrayReduce(dcSports, function(previousValue, value) { return previousValue & "<li>#value#</li>"; }, "<ul>" ) & "</ul>"; writeOutput(ul); Result is just the Array turned into a list • Redskins • Capitals • Nationals • Wizzards • United
  54. 54. Map and Reduce (and more) • structReduce() -- StructReduce(struct, function(result, key, value [,struct]), initialVal) rainbow = { "Red"= "Rojo", "Orange"= "Anaranjado", "Yellow"= "Amarillo", "Green"= "Verde" }; dl = structReduce( rainbow, function(previousValue, key, value) { return previousValue & "<dt>#key#</dt><dd>#value#</dd>"; }, "<dl>" ) & "</dl>"; writeOutput(dl); Result is a two column list of the key and the value: Red Rojo Red Rojo Orange Anaranjado Yellow Amarillo Green Verde
  55. 55. Map and Reduce (and more) Struct Reduce using member function syntax compared to same approach using loop (stack overflow question) myStruct = { 'age'=24, 'hair'='Blond', 'sex'='female', 'height'='5 foot 5 inches’ }; CF9 compat, convert data to array and use delimiter to add commas myArray = []; for( key in myStruct ) { arrayAppend( myArray, key & ' : ' & myStruct[ key ] ); } writeOutput( arrayToList( myArray, ', ' ) ); Modern CFML. Use struct reduction closure to convert each key into an aggregated array which is then turned into a list. writeOutput( myStruct.reduce( function(r,k,v,s){ return r.append( k & ' : ' & s[ k ] ); }, [] ).toList( ', ' ) ); Answer for both examples above: hair : Blond, sex : female, height : 5 foot 5 inches, age : 24
  56. 56. Map and Reduce (and more) • listReduce() numbers = "1,2,3,4,5,6,7,8,9,10"; sum = listReduce(numbers, function(previousValue, value) { return previousValue + value; }, 0); writeOutput("The sum of the digits #numbers# is #sum#<br>"); The sum of the digits 1,2,3,4,5,6,7,8,9,10 is 55
  57. 57. Map and Reduce (and more) week = queryNew("id,en,mi", "integer,varchar,varchar", [ [1,"Monday", "lunes"], [2,"Tuesday", "martes"], [3,"Wednesday", "miercoles"], [4,"Thursday", "jueves"], [5,"Friday", "vernes"], [6,"Saturday", "sabado"], [7,"Sunday", "domingo"] ]); shortestMaoriDayName = week.reduce(function(shortest,number){ if (shortest.len() == 0) return number.mi; return number.mi.len() < shortest.len() ? number.mi : shortest; }, ""); writeOutput(shortestMaoriDayName); Result (which spanish name is the smallest) notice it is using the elvis operator: lunes
  58. 58. Map and Reduce (and more) Filter() arrayFilter( array,function(arrayElement, [,index, array]) {return true|false;} ); Note: CF 11 - the callback functions of all the filters have access to the entire array/list/struct apart from the current element • ArrayFilter Filtered = arrayFilter([“myNewBike”, “oldBike”], function(item) { return len(item) > 8; }); Answer => [1]
  59. 59. Map and Reduce (and more) arrayFilter( array,function(arrayElement, [,index, array]) {return true|false;} ); • ArrayFilter Filtered = arrayFilter([“myNewBike”, “oldBike”], function(item) { return len(item) > 8; }); Answer => [1]
  60. 60. Map and Reduce (and more) structFilter( struct,function(key, value) {return true|false;} ); fruitRatings = {apple=4,banana=1,orange=5,mango=2,kiwi=3}; favoriteFruits = structFilter(fruitRatings, function(key, value){ return value >= 3; }); writedump(favoriteFruits); Answer (struct of values GT 3) Apple=4 orange=5 kiwi=3
  61. 61. Map and Reduce (and more) listFilter( list,function(listElement) {return true|false;} ); numbers = "1,2,3,4"; odds = listFilter(numbers, function(v){ return v MOD 2; }); writeDump([odds=odds]); Answer (ordered struct) Odds 1,3
  62. 62. Map and Reduce (and more) queryFilter( query,function ); teams = queryNew("id,en,mi", "integer,varchar,varchar", [ [1, "Washington", "Redskins"], [2, "Washington", "Nationals"], [3, "Washington", "Wizzards"] ]); teamsWithoutK = teams.filter(function(teams, index, query){ return !teams.mi.find('k'); }); writeDump(teamsWithoutK); Answer Returns a query of teams that do not have a K in the name
  63. 63. Map and Reduce (and more) Each() arrayEach([1,2,3,4,5,6,7], function(item) { writeOutput(dayOfWeekAsString(item) & “<br>”); }); Answer: Sunday Monday Tuesday Wednesday Thursday Friday Saturday
  64. 64. Map and Reduce (and more) ArrayEach arrayEach( array, function(any currentObj) { } ); arrayEach([1,2,3,4,5,6,7], function(item) { writeOutput(dayOfWeekAsString(item) & “<br>”); }); Answer: Sunday Monday Tuesday Wenesday Thursday Friday Saturday
  65. 65. Map and Reduce (and more) structEach structEach( struct, function(key, value) { } ); structEach({one:1, two:2}, function(key, value) { writeoutput(key & “:” & value); }); Answer: ONE: 1 TWO: 2
  66. 66. Map and Reduce (and more) listEach listEach( string, function(string, delimeter) { } ); listS = “Redskins, Nationals, Wizzards”; listEach(listS, xClosure); Function xClosure(empname, index) { writeoutput(empname & “ at index:” & index & “<br>”); }; Answer: Redskins at index: 1 Nationals at index: 2 Wizzards at index: 3
  67. 67. Map and Reduce (and more) queryEach queryEach( query, function ); teams = queryNew("id,en,mi", "integer,varchar,varchar", [ [1, "Washington", "Redskins"], [2, "Washington", “Nationals"], [3, "Washington", "Wizzards"] ]); function printQuery(any Obj){ WriteDump(Obj); } WriteOutput("QueryEach: "); QueryEach(teams, printQuery); Answer: Redskins Nationals Wizzards
  68. 68. Map and Reduce (and more) • Resources • map and reduce & more with adam: http://blog.adamcameron.me/2014/02/coldfusion-11-map-and-reduce.html • map reduce: https://hacks.mozilla.org/2015/01/from-mapreduce-to-javascript-functional-programming/ • js working example of each: http://elijahmanor.com/reducing-filter-and-map-down-to-reduce/ • ColdFusion 2016 query iterations: http://blog.adamcameron.me/2016/02/coldfusion-2016-query-iteration.html • Map/reduce and higher order functions: http://ryanguill.com/functional/higher-order-functions/2016/05/18/higher- order-functions.html • Member functions: https://cfdocs.org/member
  69. 69. Final Thoughts/Resources • These topics were only some more modern concepts for CFML. • Where to get more information from CFML Community • Adobe Wiki/help docs • CFDocs.org • Cfblogger (put in aggregator like feedly) • Slack Channel – 2000+ cfml users https://cfml.slack.com/ • Trycf.com (place to run examples) • CFScript.me (convert tag – script) • Twitter, Facebook, youTube, Vimeo and other social sites Dan Fredericks @fmdano74 fmdano@gmail.com I am on most social networks, twitter, facebook, G+, LinkedIn Download Original Presentation: http://bit.ly/2cIjXuI Special Thanks to Carl Von Stetten, Adam Cameron, Adam Tuttle, Ray Camden, Sean Corfield, and Brad Wood for examples

×