Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Tuesday, September 15, 2020

#100DaysOfClojure (Day [14] flow-control-cont-3)

Today I will be looking at exception handling. Clojure provides the normal try-catch-finally block to catch exceptions and has the following general syntax


(try
   (code)
   catch Exception e1)
(Exception Handler)
(finally
   Cleanup code)

Here is an example

(try
  (/ 2 0)
  (catch ArithmeticException e
    "divide by zero")
  (finally
    (println "cleanup code")))
cleanup code
=> "divide by zero"

You can throw an exception in the following manner

(try
  (throw (ex-info "There was a problem" {:causes "example"}))
  (catch Exception e
    (println ex-data e)))

#object[clojure.core$ex_data 0x5f1df0de clojure.core$ex_data@5f1df0de] #error {
:cause There was a problem
:data {:causes example}
:via
[{:type clojure.lang.ExceptionInfo
   :message There was a problem
   :data {:causes example}
   :at [leinproj.core$eval1739 invokeStatic form-init10068916269700534711.clj 2]}]
:trace
[[leinproj.core$eval1739 invokeStatic form-init10068916269700534711.clj 2]
  [leinproj.core$eval1739 invoke form-init10068916269700534711.clj 1]
  [clojure.lang.Compiler eval Compiler.java 7177]
  [clojure.lang.Compiler eval Compiler.java 7132]
  [clojure.core$eval invokeStatic core.clj 3214]
  [clojure.core$eval invoke core.clj 3210]
  [clojure.main$repl$read_eval_print__9086$fn__9089 invoke main.clj 437]
  [clojure.main$repl$read_eval_print__9086 invoke main.clj 437]
  [clojure.main$repl$fn__9095 invoke main.clj 458]
  [clojure.main$repl invokeStatic main.clj 458]
  [clojure.main$repl doInvoke main.clj 368]
  [clojure.lang.RestFn invoke RestFn.java 1523]
  [nrepl.middleware.interruptible_eval$evaluate invokeStatic interruptible_eval.clj 79]
  [nrepl.middleware.interruptible_eval$evaluate invoke interruptible_eval.clj 55]
  [nrepl.middleware.interruptible_eval$interruptible_eval$fn__971$fn__975 invoke interruptible_eval.clj 142]
  [clojure.lang.AFn run AFn.java 22]
  [nrepl.middleware.session$session_exec$main_loop__1072$fn__1076 invoke session.clj 171]
  [nrepl.middleware.session$session_exec$main_loop__1072 invoke session.clj 170]
  [clojure.lang.AFn run AFn.java 22]
  [java.lang.Thread run Thread.java 832]]}
=> nil

ex-info can contain a message and a map, and ex-data allows you to retrieve the map or return nil if not created with an ex-info.

(println “Bye 4 Now!")  

Monday, September 14, 2020

#100DaysOfClojure (Day [13] flow-control-cont-2)

My apologies, as fun as Clojure is, I managed to drag myself away and took a 2 day break. Today I will look at recursion in Clojure. First let's I will look at recursion as used in most non functional languages where the function is called within the function(the function calls itself). But this usually only works up to the size of the stack frame. Lets look at a factorial function as a recursive example (The N at the end of the number just lets Clojure REPL know that it is a Clojure BigInt) 


(defn n! [n]
  (if (<= n 1) 1 (* n  (n! (- n 1))  )))
=> #'leinproj.core/n!
(n! 4N)
=> 24N
(n! 40N)
=> 815915283247897734345611269596115894272000000000N
(n! 400N)
=>
64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000N
(n! 4000N)
Execution error (StackOverflowError) at leinproj.core/n! (form-init10068916269700534711.clj:2).
null

In order to overcome the stack frame limits Clojure includes a recur function that does a tail call optimisation. The same factorial function can be implemented as follows

(defn n!-with-recur [n]
  (loop [value n total 1]
    (if (= value 1)
      total
      (recur (dec value) (* total value)))))
=> #'leinproj.core/n!-with-recur
(n!-with-recur 4N)
=> 24N
(n!-with-recur 40N)
=> 815915283247897734345611269596115894272000000000N
(n!-with-recur 400N)
=>
64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000N
(n!-with-recur 4000N)
=>
18288019515140650133147431755739190442173777107304392197064526954208959797973177364850370286870484107336443041569285571754672461861543557333942615617956996716745284831597317498818760937482804980419576512948720610558928129788097800620593429537705326740624453884285091743951756746144447362378722469436194575929579900114212973360658998073977714697261205048663725936337490404066097966637170254021348800944280342285355946649681316260163459743803577175903394733170076841764779082166891184529324230033414145497801832598218518406552257097392530024582738982919104406782168708871495603501905867399966298798534877747923179195791416504408054878974770308650707120878837624986576073340449414854578367383301715706358194127400849855604080473305196833482408079420964275187538889115296655522397723924887154624810659788321005620558369604778657904771918388054319251513981954296741688447246185021250402225010116433016818588036690180177691461779713104301640395708274734701186772756966064611023656528765138735704190876200697145804692125236821066805337175220605745377557452592208653939853278523841448314026548802309860391087939783218946129582647928430739985554883806198749831633640196211202756086016039171607744078776876219661603702759454887945247605749205543464095883664514960293873244842409803801480566600124415293789831496309554117113888561569494314926134470477513516416560102984058751906208865570183683850791317395702861350821464653600469443279077733978568711404244774089509216727922510660941411716412467443445414001188915966547283773988670739792818897314762082568914041952211779194055311405259158538932388745292324386826830135904886472292289993848482289254307628467614523292519222687689180219788377184005246290896703260524910362136627321135976515358528150143796798116836263053229733971612275184896139539613129329008449214723196703789119820971205922195513915546814704778682373487718946560822811623038853887054357316290622378472322045316639418491798517077275839637525427601452961835674484434498885698840692468550825765131610925966585339561854456154229048295742274725126218799745448031391826295221114381890600683208441558088271228618006589059444108806652992787854634497487158675770983422610936590600627170500972481399444145398522756870626097250230229195799277299921844954715690883242553569256657132515663544931830393317518828986443942138971609142621397646808351809694603734872977984148002699965137870448199866167162949256435040416146886823942144459105175033488395869910405207521329016842673168563837531518918339627724066152933627236730561155418227888673513937454508103826102827706121560330906016404162420051373313654570111102003319577878502216919170112074608722852376799943191590480651623958062982829452035227119036502426583752512199824089725611711059153935434418985109241404135069047109527514730648502064630431371185922523036941621026392783813435540195800531988645430344745298845640017082732623248838473771603478336326662579219137601422632057648758807935233915527562817942378675243919886800056209434731407685691942327092464101136254795499159351103542747723434544436366313104996373661654989465498180892716462805042227038222104784062626027480151567377841821316292095295686368619300417863327530764301323081902435971165925163513225511176258919471673437553320934916910573999020966087207663133871516530391787535755420348174519954013015999193335205032571176460105005716115305748669364682675265014310223271762807620242805617435594927890676408953057384890719681225840400396698155624793888816156585043604782961704971397764959404751358445856914581957186533573207690355894150776647727994156425641953755517727965486096675384222232344185537279888780570854092084221993660761154788359777439798490851148031275123759286793224660188593768897291749180357297185650430735063126035278321749629995702200115722386600046772883018963166273463715186812543356173550341233310175600817771447170656517505385258772069067139665478506263898380526394388218036388768999161538645432932116471146392562992204259450889291928261780531925618148311151259088519869787637913607866079920830781433275298468534248595471485354420794089854693167644320115900404444471266030942746376074187982809857292874382829734306879420308783010740784767155894363033186129183748698373599293267795620690003900348542140553208244771165593739117369452474295075445169488356550100854423929030967163401348223503674045821834526710830392520955478859202303175309815706259592416130388770535449570146586161954289529234209342432075461261173246383180702862172009624828852517861214008242944903162464816939278645210656431141653019224783906038062818006434258491952705341708781231767324026544165240012431457995565227331912056216396141277926932316783631899833106810492890045890947294731794016389385348294079360921757589715698098491612254898203787546124091057862387229987442131738499764391062422228395736099751277880661280909246369674792326056952220508861243875642482808175793303703933394191224832165950388337931626643339913192088808753619030386928808349931733881036690498513779587801764477865791351420222949860738228995728065763459283625096944678593378349990211317403358327367677358882377095918185840441346045760435580063918587956888086127034558064154832456098224664532422114583653763989534559801683261113731162039500068729224661509382267286483841867542303955164213391663536072749966590737898408144092699675796793165775891429992491955485860639629542416955757565163223827874193321274119938618709482020627749094917473754346320653165690129809741806883246764053966717253521140010801409998318494470531219051920354752556183478378238398583402765337923843167749738355049636714529840534145950376598809459294819192486096200503652538835417613002983933634477053826438814791235363934440952835213240806543802505241445900981152753843778634021300832293332432473400040109754281828950625464331409151961292319287863535740382445771128522343533054993071872524564127962306298218521662304206610010638488461150361786151832595182055013210238035059473479841417644445066550217093994746959565730463201996845756999575031950401331385688683576883429289274419202816101239071817771853612534620088858074904095239406471009098851796038360101243053736361346640211872570375441319261567131238168652234864182359667285536913841122976956009892970909409178865928472056691904571596961458646895132972589012090613887584436018692038947475932753085268106507554394567201654757930957224629573401948677157237825005540282635839895509019254240256916422227590032685003087320017232658420681209681389364174854034319152111706246564733896551636271748411627920466475472421243033805492052542237647091252577811952376244836844025673570936216945539206875730684120187779664758451508678786539887154966732995692212544207529457534936853900663520665102592278581210192104846016594846265525000394264201946315492667174670489454576610993722063668720936949698308641684437046485292906040368218708947194882991333823400676584552108673913669306118549159369734833071319506680872661886898225398171896329288732499509337836463164384614967690283284184136334006184670970038275153458133098776493171693249836721707632973537518273692928527497068121779606865163943692606596848941143683627629169873171114739189794632775706536177409526869936538136348369630762610163490694986911903178859927739423796596582439105912599204583810744740479342404550513976713360591833475711496976836332005885151231030818986389033126325119226309584818058301429763149472903925739659774337307109687940297813700796873400566095281249251559137923743113469044584820584542770746490047535898370961450995287930441328833542933636539386097851378739174078158132593877463567524868470795313740375647059352650583871001646082364842709333314532933141725314262510333047099681128329792983694287727106008519184538377065089964546579000542260452715147077137452076302879112802094308224402060706282308208678850263037733351444756065285721900833083634023860920356321356382318484421995141074387149942542550133039926139155010190614633196727199469768170121209097613598302048321148497175007150184555423280152476407230065108963493864309805262458731715886593175689747530567359088332598961192319881186961400055356294945140450806114214490420494488195417136403967132286869444062615622815233336396279517485469862880809956041938378161336156979526713793454354319018535526139196959277008828634440008764782171726908279132449346924807112458895951881542382952497102061566169481361027449429416228859029591798532192088531772405831332410104172391828682208239266557146168642210154401086974397003647170356217905465594944933170065175291981240572835024374361017977695084363373226470846255498368067535698751768103817520605779489720985090002595078926475029239124403277040719184010486962844211160986922952144938430963756963408787147933184107904312838985994963982784496688190643908936394858404598837762653245968848299901455260080572627872653099337092686312650606546084656202210845053932679131706841390889951865628810708670194485207654079244417321332232196041180225814997707988397637369268804955010409293139079608620689856756139863786355461818276369292665568749282154818479663283704713663666842236273009790537968973379093662517795316051746410279831975339791651704861188979834156418998505732384020730350075052669695594594753081616632885311572351609352631187129393729557398993321794518158269658073683417584260274184235030846683698193879109933863561435059993549597333514217973995915742796206889856584584493875193805504685107321011420502217815128118404137521250590361329385146997427292035829509205811367395885622247504950811752188165627552137681095618860955664505372763469788466067973748736658759105548049054658237200096293754479296344115915560231138432518248450383276234795400180535655551222536669390799317067896797756236783441752907948891802488298281245615590113512482344591092230909649423933991714557108941323849548468680509335203770970493785006636718394242326057416155509029270066096293813080877339787718442773014833232754755736783313789547145535129557193581885962158684756484475219230828423777756012721234731368785218564362953263092286535139160440838713013861328416662947756104857391740722209360021068158824717926850831589591367302143596625426553706038593255843919505223140871543995210720444637571268651195165483531243799087083070940544241515809139594158704843980567202482856647644447362604252961907705738740354460336586792214638225365973993001974668174157206242597452556046629209551599663117912609702944345176608757619561247872050409609062772362769045711709729061066411540898769707847042980034982033351136308779676287974627667703893888026848748953201438481632037717854462054861859986684636917120883602793194058658599425778515519713798214407689849211487929150179918547200558584524139792439377469676039518101451697712860634235352474290575260172151562129240720796835619967878383018961055921622371480562682714603085506932806187937976625431071742833007749235636990700120567425836156233607547500827789537909071263596294926763891075439575973972560478399510790078797663071024149826759934524980569432847819403219226207098701759952415628476519584752248050578584198211799092030838909208236225141975964892778944163008811179723219354847713753084628828883321692575327835658786892010648865205021985527642612795652759365359359048052205587306960853879351302215329380382709288672566169552660197788055450054177652374955319992805345989662399494012874012278677451052584166987084866267245492968785684175508510910492913793478551456991152291522750377308973310200505007906906671435839262115546753934391579860133029544403932422271218975046896384482252108820546415274174791693426071019927278518520520164621127271231748277979659289204850823018535192067323372368224831050642902153626845618478009622824733150764188329304815843651352730897836727021023023627320228373645802602496000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000N

Using 4000 in this case did not result in a stack overflow error, but instead its factorial was calculated. recur is typically used with a loop function which binds values and acts like a let.

A side note is that Clojure provides better ways to calculate a factorial, but the factorial was a simple way to look at recursion in Clojure, but is not the best way to do it.

Tomorrow I will look at exception handling in Clojure as the last of the flow control mechanisms.

(println “Bye 4 Now!”)  

Friday, September 11, 2020

#100DaysOfClojure (Day [12] flow-control-cont)

There are a few more flow control concepts that we need to cover.

The cond function allows a series of tests and expressions with each test evaluated in order and the first true expression returned.  A small additional details in the example is the let function which binds a name to a value. Lets look at an example:

(let [x 7]
  (cond
    (< x 3) "x is less than 3"
    (< x 7) "x is less than 7"
    (< x 10) "x is less than 10"
    (< x 20) "x is less than 20"))
=> "x is less than 10"

You can even add an else statement in the event of no true expressions

(let [x 7]
  (cond
    (< x 3) "x is less than 3"
    (< x 7) "x is less than 7"
    :else "x is greater than or equal to 7"))
=> "x is greater than or equal to 7"

Then there are case expressions which are implemented as follows

( let [x 7]
  (case x
    7 (println "x is 7")
    10 (println "x is 10")
    (println "x is neither 7 nor 10")))
x is 7
=> nil

Tomorrow I will look at iterations and recursion.

(println “Bye 4 Now!”)  

Thursday, September 10, 2020

#100DaysOfClojure (Day [11] flow-control)

 In Clojure everything is an expression because everything returns a value. Even a block of multiple expressions will return the last value. There are 3 basic flow operators: if, when and do, which themselves are also expressions.


If has the following basic form

if boolean 
    then
    optional else

Here is an example of an if expression
(if true
  "It is true"
  "It is false")
=> "It is true"

The do function lets you wrap multiple expressions and forms and looks as follows
(if true
  (do
    (println "First Form")
    "True Expression")
  (do
    (println "Else Form")
    "False Expression"))
First Form
=> "True Expression"

The when operator is a combination of the if and do without the else expression
(when true
  (println "True Form")
  "True Expression")
True Form
=> "True Expression”

;Or when it evaluates to false 

(when false
  (println “False Form")
  “False Expression")
=> nil
 
You can check if a value is nil with the nil? function as follows
(nil? nil)
=> true

But be aware that the nil in an if expression evaluates to false
(if nil
  (do
    (println "First Form")
    "True Expression")
  (do
    (println "Else Form")
    "False Expression"))
Else Form
=> "False Expression"

Clojure also provides equality = and boolean operators or and and
(= 1 1)
=> true

(and 1 1)
=> 1
(and 1 0)
=> 0

(or 1 1)
=> 1
(or 1 0)
=> 1
(or 0 0)
=> 0

That’s it for today, will see you again tomorrow. Not quite sure what I will cover tomorrow, let it be a surprise…

(println “Bye 4 Now!”) 

Wednesday, September 09, 2020

#100DaysOfClojure (Day [10] Sets)

A Set is a collection with unique elements. They are like mathematical sets, unordered and unique. They are used for checking whether a collection contains an element or removing an arbitrary element. You will notice they can contain any type including functions.


You create a Set as follows

#{1 "Hello" :anytype 22/7}
=> #{1 "Hello" 22/7 :anytype}

You can add an element to a Set as follows

(conj #{1 "Hello" :anytype 22/7} 0x0A)
=> #{1 "Hello" 22/7 :anytype 10}

You can remove an element from a Set as follows

(disj #{1 "Hello" 22/7 :anytype 10} 0x0A)
=> #{1 "Hello" 22/7 :anytype}

You can check containment in a Set as follows

(contains? #{1 "Hello" 22/7 :anytype 10} 22/7)
=> true

(contains? #{1 "Hello" 22/7 :anytype 10} :wrontype)
=> false

You can combine 2 Sets as follows

(into #{1 "Hello" 22/7 :anytype} #{0x0B "World" 1/3})
=> #{1/3 "World" 1 "Hello" 22/7 11 :anytype}

You can also do Set functions like union, difference and intersections. These functions exist in the Clojure.set namespace and has to be used as such.

You can do unions of Sets as follows

(clojure.set/union #{1 "Hello" 22/7 :anytype} #{0x0B "World" 1/3})
=> #{1/3 "World" 1 "Hello" 22/7 11 :anytype}

You can do a difference of Sets as follows

(clojure.set/difference #{1 "Hello" 22/7 :anytype} #{0x01 "Hello" 1/3})
=> #{22/7 :anytype}

And finally you can use the intersection function on Sets as follows

(clojure.set/intersection #{1 "Hello" 22/7 :anytype} #{0x01 "Hello" 1/3})
=> #{1 "Hello"}

Tomorrow I will look at some of the flow functions in Clojure

(println “Bye 4 Now!") 

Tuesday, September 08, 2020

#100DaysOfClojure (Day [9] Maps)

Today I will look at Maps, one of the most important collection types in Clojure. Maps are collections of key-value pairs. Keys can be of any type in Clojure including functions, lists, other maps etc. The are 3 types of maps in Clojure: Hash Maps, Sorted Maps and Array Maps. Sorted maps keep the key value pairs in a certain order which implies that a lookup time may not be constant and it also allows you to traverse the values in the order of the keys. Sorted maps have a constraint in that the keys have to be comparable. 


You can create them as follows

; Hash maps
{"number" 1 2 2.25 :pi 22/7}
=> {"number" 1, 2 2.25, :pi 22/7}

or alternatively

(hash-map "number" 1 2 2.25 :pi 22/7)
=> {:pi 22/7, "number" 1, 2 2.25}

;Sorted maps
(sorted-map "number" 1 "2" 2.25 "pi" 22/7)
=> {"2" 2.25, "number" 1, "pi" 22/7}  ; note the order

; you can also sort using a custom comparator
(sorted-map-by #(< (count %1) (count %2))
               "number" 1 "2" 2.25 "pi" 22/7)
=> {"2" 2.25, "pi" 22/7, "number" 1}

You can lookup values as follows

(get {"number" 1 2 2.25 :pi 22/7} :pi)
=> 22/7

or alternatively use the key as a function

(:pi {"number" 1 2 2.25 :pi 22/7})
=> 22/7

if you don't find the key

(get {"number" 1 2 2.25 :pi 22/7} :missing)
=> nil

 You can add new key value pairs as follows

(assoc {"number" 1 2 2.25 :pi 22/7} :association {:a 2.00 :b 5.78})
=> {"number" 1, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}}

You can remove key value pairs as follows

(dissoc {"number" 1, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}} :pi )
=> {"number" 1, 2 2.25, :association {:a 2.0, :b 5.78}}

You can get a list of all the keys as follows

(keys {"number" 1, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}})
=> ("number" 2 :pi :association)

You can also get all the values as follows

(vals {"number" 1, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}})
=> (1 2.25 22/7 {:a 2.0, :b 5.78})

You can also combine maps as follows

(merge {"2" 2.25, "number" 1, "pi" 22/7} {"number" 1, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}})
=> {"2" 2.25, "number" 1, "pi" 22/7, 2 2.25, :pi 22/7, :association {:a 2.0, :b 5.78}}

That's all for today, tomorrow I will move onto Sets

(println "Bye 4 Now!!")

Monday, September 07, 2020

#100DaysOfClojure (Day [8] Vectors)

Vector is another collection data structure that allow random access and add new elements to the end of the collection. 


Here is an example of how you declare a vector:

[1 "Hello" :anytype 22/7]
=> [1 "Hello" :anytype 22/7]

or alternatively

(vector 1 "Hello" :anytype 22/7)
=> [1 "Hello" :anytype 22/7]

You can retrieve any element by using its index which is zero based

(get [1 "Hello" :anytype 22/7] 1)
=> "Hello"

You can get a count of elements as follows

(count [1 "Hello" :anytype 22/7])
=> 4

You can add elements as follows:

(conj [1 "Hello" :anytype 22/7] 2.25)
=> [1 "Hello" :anytype 22/7 2.25]

You can remove an element from the end of the Vector as follows :

(pop [1 "Hello" :anytype 22/7 2.25])
=> [1 "Hello" :anytype 22/7]
 
You can also remove a subset of elements from the vector as follows:

(subvec [1 "Hello" :anytype 22/7 2.25] 1 3)
=> ["Hello" :anytype]
Note the start index is inclusive while the end index is exclusive.

You could also use the nth function as follows:

(nth [1 "Hello" :anytype 22/7 2.25] 2)
=> :anytype

You could also replace values in a Vector using the assoc function

(assoc [1 "Hello" :anytype 22/7 2.25] 1 2 2 3)
=> [1 2 3 22/7 2.25]


That's all on Vectors, tomorrow I will look at Map Collections

(println "Bye 4 Now!")

Sunday, September 06, 2020

#100DaysOfClojure (Day [7] (lists))

The Clojure programming language is designed around data processing which includes the code as data. Today I get into the very foundations of programs in Clojure, the collection data structures. Remember that data in Clojure is immutable so in order for Collections to be efficient they need to be persistent, which means that all the copies have to share the common data. The are 4 collection types, Lists, Vectors, Maps and Sets. And these collections share a set of core functions :

  1. conj - returns a new list with the new add item added
  2. seq - returns sequence to of the collection
  3. count - return the number of items in a collection
  4. empty - returns an empty collection of the same type
  5. = - determine the value equality of one or more collections

I will look specifically at Lists today, and lists in Clojure function similar to linked list in that you have to traverse from start to end (or head to tail). New elements are inserted at the start/front/head of the list. 

You declare a list in the following way

'(1 "hello" :anytype 22/7)
=> (1 "hello" :anytype 22/7)

You may have noticed that the list can contain any types including functions (code)

You can add an element as follows:

(conj '(1 "hello" :anytype 22/7) 2.25)
=> (2.25 1 "hello" :anytype 22/7)

You can count the number of elements in a list

(count '(2.25 1 "hello" :anytype 22/7))
=> 5

You can get the first element as follows:

(first '(2.25 1 "hello" :anytype 22/7))
=> 2.25

You can get the nth value as follows:

(nth '(2.25 1 "hello" :anytype 22/7) 3)
=> :anytype

You can also get the whole list except the first by using the rest function as follows:

(rest '(2.25 1 "hello" :anytype 22/7))
=> (1 "hello" :anytype 22/7)

Equality works as follows:

(= '(1 2 3) '(1 2 3))
=> true
(= '(1 2 3) '(1 2 4))
=> false

There are a few other functions, but will leave that to you to explore. 

Since I have reached a point of having sufficient knowledge of the language to build something real, I will now turn my attention to trying to solve a real life problem as a project. If you have any suggestions for a project please leave a comment...

Tomorrow I will look at Vectors

(println "Bye 4 Now!")

Saturday, September 05, 2020

#100DaysOfClojure (Day [6] Functions Continued)

Today I am continuing with 3 more useful function concepts: How to define functions, anonymous functions and using apply with functions


Functions can be defined in two ways:

(defn name [params] (body))

(def name (fn [params] (body))

 defn is a macro (which I get to some time in the future) doing both a def and fn

The next useful concept is anonymous functions which have a shortened form #() and parameters are specified with a % symbol. Example:

(#(println %) "Hello World!")
Hello World!
=> nil

 You can also use the apply functions on function for each parameter, for example

(apply + '(1 2 3 4))  ; applies the + function on all the values in the list
=> 10

That's all on functions, tomorrow I will look at collections

(println "Bye 4 Now!")

Friday, September 04, 2020

#100DaysOfClojure (Day [5] Functions)

The excitement is building up, today I played with functions. A Clojure function has the following structure

(defn name params (body))

Here is a simple example of a Hello World function definition

(defn sayHello [toName] (println "Hello, " toName))

To call it looks like below with its output

(sayHello "Ahmed")

Hello,  Ahmed
=> nil

There are multi-arity functions which can take a different number of parameters so for example (indents and next line are for readable purposes only):

(defn saySomething 
    ([] (saySomething "Hello world!")) 
    ([msg] (println msg)))

;call the function
(saySomething)
Hello world!
=> nil

(saySomething "Goodbye")
Goodbye
=> nil
 
And there are Variadic Functions which may define a variable number of parameters, for example:

(defn sayManyThings [& thingsToSay] (println thingsToSay))
=> #'leinproj.core/sayManyThings

;call the function
(sayManyThings "Hello" "to" "Ahmed" "and" "friends")
(Hello to Ahmed and friends)
=> nil

There are a few more concepts with functions which I will continue with tomorrow

(println “Bye 4 Now!”) 

Thursday, September 03, 2020

#100DaysOfClojure (Day [4] Basics)

Today I can dip my toes into the language itself. I will be looking at the some of the syntax and forms, Clojure refers to valid code as forms. Clojure has literals which consist of primitive data types, symbols and collections. 


Clojure also has 2 kinds of structures, literals and operations and which follow this format:

(operation argument)

The ( represents a list and an invocation
The operation is a symbol and a function
The argument can be primitive data, a collection or code

Example of adding integers
(+ 1 1)
=> 2

Example of adding ratios
(+ 1/2 1/3)
=> 5/6

Example of subtracting floating point numbers
(- 1.5 0.2)
=> 1.3

Example of adding Hexadecimals
(+ 0x01 0x02)
=> 3

Example of system documentation
(doc +)
-------------------------
clojure.core/+
([] [x] [x y] [x y & more])
  Returns the sum of nums. (+) returns 0. Does not auto-promote
  longs, will throw on overflow. See also: +'
=> nil
*note, even the documentation follows the format, that is how consistent the structure is

There are 4 types of collections : Lists, Vectors, Maps and Sets. All collections are immutable and persistent.

Examples of the collections
 
'(1 2 3)     ; list : they are ordered and can only be accessed by traversing the order
[1 2 3]      ; vector : vectors can be accessed with a index
#{1 2 3}     ; set : the elements are unique and they provide set operations ( union, intersection etc.)
{:a 1, :b 2} ; map : stores key-value pairs


Tomorrow I will look at some function definitions 

(println "Bye 4 Now!")

Wednesday, September 02, 2020

#100DaysOfClojure (Day [3] IntelliJ + Cursive)

With the wide variety of editors/ides available, it was a difficult decision to make. So how did I make this decision you ask? I made the decision based on the quality of the documentation and my familiarity with the editor. Hence I chose IntelliJ and the Cursive plugin. Cursive provide 3 licenses, personal, commercial and non-commercial. Since I am only using it to learn Clojure, I chose the non-commercial licence which is a free 6 month renewable licence.


Getting it up and running was as easy as following the cursive documentation. 
I created a leiningen project which created a folder structure and file with a defined function foo which prints the infamous Hello World message. I loaded the file into the REPL environment and called the function in the REPL input window

(foo "Ahmed Chicktay says ")

Which resulted in 

Ahmed Chicktay says  Hello, World!
=> nil

Here is an image of the entire development environment





















Tomorrow I will look at Clojure literals and if time permits, some of its collections.    

(println “Bye 4 Now”) 

Tuesday, September 01, 2020

#100DaysOfClojure : (+ Day [2] Tools)

Today was a busy and tiring day, so I decided to keep it light and explore the tools available for Clojure. The first tool of importance is Leiningen. It is a build automation and dependency management tool for the Clojure programming language written in Clojure itself. It integrates well with Maven repositories and the Clojars repository for Clojure libraries.  On an Apple Mac you can install Leiningen very easily using homebrew.

















Leiningen provides the following automated tasks to name a few:

  1. The ability to create projects
  2. Compile and package projects
  3. Run projects
  4. Run tests
  5. And more….

There is an alternative build tool called boot, but delving into that is for another day...

Once that was installed I thought I would look for an editor that is Clojure aware and there are a few options in no specific order

  1. Emacs with Cider plugin
  2. Atom with nrepl
  3. Cursive plugin for IntelliJ
  4. Nightcode
  5. Counterclockwise a plugin for Eclipse
  6. Vim with plugins
  7. Light table
  8. SublimeText with SublimeREPL
  9. Netbeans Clojure
  10. VS Code with Calva plugin

I haven’t decided which editor to go with yet, I will leave that for day 3. 

(println “Bye 4 Now”)  

Monday, August 31, 2020

#100DaysOfClojure : (#Day [1] Intro)

I guess you wondering why I chose Clojure as a language to learn as a 100 days of code challenge. Well, functional programming has always intrigued me, but I never could find the time to tinker with it. On discovering that Clojure was designed by Rich Hickey, someone whom I knew understood simplicity, I figured it would be the perfect language to learn from the vast functional ocean. And when you can’t find the time, you have to make the time, so here I am hoping to see out my hundred days. 

My journey started following my usual process: searching duckduckgo for Clojure which led me to this wonderful site: https://clojure.org which has everything one needs to get going. I did some reading on the language to create a mental context and find a starting point to get some running code. 

Clojure is a dynamic general purpose programming language hosted on the Java Virtual Machine (JVM). It is a functional programming language with special features for dealing with concurrency and also a dialect of Lisp. 

My goal for the day is to run the iconic Hello World app of course. I opened a Terminal on a Mac and checked that I have java installed and then used brew to install Clojure. The instructions on the Clojure website are very easy to follow and within minutes I had the REPL up and running











Yippee, that was easy enough for today. I will now spend some time reading The Joy of Clojure…

Tuesday, November 08, 2016

I Am A Failed Consultant

I get great joy and personal satisfaction from assisting someone or a paying client with the IT challenges they face, specifically in software development. Some 20 years ago, I discovered this about myself, and realised that consulting and coaching was my calling in life and have dedicated myself to it. I have spent years, honing the skills to help mentor, coach and consult with my clients. The mantra of my service and the measure of my success is that I become replaceable. If I cannot be replaced then I have failed. 

So why do I think I have failed? Over the years as I look back at my clients requirements, I notice that most of them were looking for a technology that would solve their problems, but instead I sold them problem solving techniques to better understand their problem spaces. Oftentimes, upon analyzing the issues that a client is struggling with and trying to solve with technology, I find that the real issue is a lack of understanding of the problem space. Badly designed systems irrespective of the technology is usually the result of not understanding the problem space sufficiently. Changing the technology is not going to fix this, only resolving the problem space will. So what ensues is a new, badly designed system, with new technology. Yes, while the new technology may or may not ease the problem somewhat, it does not remove the underlying cause.  

I could easily sell my clients the latest fad like micro architectures, agile processes etc. and they will possibly eat it up, love me and I would feel really successful, and in a few months time I could sell them the next new fad again and so and so on. But for most IT departments the latest technologies is the least of their problems in my opinion, so instead I provide them with pragmatism and a reality check, which no one seems to want to hear….So I have failed, and end up trying to rescue these new technology projects.

Tuesday, January 14, 2014

JavaScript: Splicing an Array

This JavaScript blog series will be posted more regularly in 2014. To kick off, lets look at how to dynamically add and remove items anywhere in an array. Arrays in JavaScript have a splice function to do just that.

It has the following syntax

array.splice(index, quantity, item1, ..., itemX)   returning an array

where the parameters are defined as:

index  :  it is required and specifies the position at which to add or remove items. If it is negative it will calculate from the end of the array.

quantity : it is optional and specifies the number of items to be removed from the index onwards. To not remove any items, set it to 0. If it is not specified it will remove all elements after the index.

itemX : it is optional and is the items to be added to the array at the specified index.

Lets define an array

var myArray = [1,2,3,4,5]

Now lets remove all elements from index 4 onwards

myArray.splice(4)

This results in the following array

[ 1, 2, 3, 4 ]

Now let us add some elements to our array starting at index 4,

myArray.splice(4,0,5,6,7,8,9,10)

This results in the following array

[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

Now lets replace elements with values 4 and 5 with 11 and 12

myArray.splice(3,2,11,12)     //remove 2 elements at index 3 and add 11 and 12 at index 3

This results in the following array

[ 1, 2, 3, 11, 12, 6, 7, 8, 9, 10 ]

Now lets remove elements with values 11 and 12 from the back of the array

myArray.splice(-7,2)

This results in the following array

[ 1, 2, 3, 6, 7, 8, 9, 10 ]

Pretty cool hey, that's enough on splicing, its time for you to experiment with it. Till next time enjoy!!!

Monday, September 09, 2013

JavaScript: Slicing an Array

Have you ever wanted just a sub section of an array? Well, with slicing an array you can do just that.

Suppose I have an array

var myArray = [1,2,3,4,5];

and I want the first 3 elements, I can do the following

myArray.slice(0,3);

which return an array with the first 3 elements

[ 1, 2, 3 ]

This does not modify the original array in any way, it just returns a new array

The function slice has the following signature,

slice ( beginIndex, endIndex ) where the index is zero based i.e. the first element in a an array starts at index 0.

You could also access the array from the end using negatives indices for example,

myArray.slice(-3, -1);

returns

[ 3, 4 ]

Next we will look at splice......until next time!


Monday, July 22, 2013

JavaScript: Length of Arrays

JavaScript arrays are dynamic and flexible with a few gotcha's. Today we will have an in-depth look at the length property, which is an unsigned 32 bit integer that specifies the number of elements in an array. Arrays have 0 based indices, therefore the length property will be the highest index + 1. Lets have a look at some examples

var a = [];

a.length   //return 0, a is an empty array

var b = [2,4,6];

b.length   //return 3

b[3] = 8;

b.length   //returns 4

b['a'] = 5;   //never a good idea to use an array as an associative array, instead use a plain object

b.length   //returns 4, non numeric indices are ignored in the length property

b[10000] = 50;

b.length   //returns 10001, the positions between 3 and 10000 are padded with undefined

Setting the length of an array will shorten it as well

b.length = 4

b.length   //returns 4, shortened the array from 10001 to 4

The safest way to empty an array is to set the length to 0

b.length = 0;   //empty's an array

Next, I will be looking at the slice and splice functions on an array, till next time.......

Friday, July 12, 2013

JavaScript: More on Arrays

So what else can you do with JavaScript Arrays? Arrays are like a swiss army knife, you can use it like an array, you can use it like an object, you can use it like a stack and like a collection, whatever suits your purposes. Arrays have the following functions available
  • length - return the total number of elements in the array
  • join - concatenates all the elements in the array into a single string separated by the parameter passed
  • concat - concatenates an array to the array and returns a new array
  • sort - sorts the array by character encoding by default or by a user defined function
  • reverse - reverses the elements of the array
  • slice - returns an array that is a subset of the original array
  • splice - can insert, remove or replace one or more array elements
  • push - adds an element to the end of an array
  • pop - it removes and returns the last element of an array
  • shift - it removes and returns the first element of the array shifting all other elements down
  • unshift - inserts elements at the beginning of an array shifting all the other element up
  • toString - converts all the elements to a string and concatenates them to a comma delimited string
  • toLocaleString - converts all the elements to a localised string and concatenates them to a comma delimited string
Pretty flexible stuff, next we will look at examples of each of these functions


Tuesday, July 02, 2013

JavaScript: Arrays

The JavaScript array construct is very flexible, and I especially love the fact that you can put anything into a JavaScript array. There is no type police breaking your code. Arrays in JavaScript are not true arrays, but an Object with special array like functionality. So how do we define an Array

var x = new Array (1, 5, "ten", "twenty");

or

var y = [1, 'a', true, 7.5, new Object()];

or

var z = [ [1, "hello"], [2, {name:"test"}]];


Array indexes are zero based and can be accessed as follows

var value = x[0]  //value will be 1

var anotherValue = z[1][1]['name']  //anotherValue will be test

Array indexes are generally integers greater than or equal to 0 and less than 232 - 1, anything else would be converted to a string and looked up as a string.

Arrays can also act as a dictionary with ease, using the x variable defined above, you could do the following

x['a'] = 12345

Yip the power of arrays in Javascript is terrifying, but liberating. I will look at some other array functionality in the next instalment