Fork me on GitHub
#clojure-miami
<
2015-12-10
>
bryce00:12:32

i’ll do my best to answer questions it# /cc @christianromney @adrianm

bryce00:12:41

(although i don’t know cljs

christianromney00:12:45

thanks @bryce much of your clojure knowledge will apply anyway

christianromney00:12:58

a reading from the Gospel of Hickey 😛

christianromney00:12:23

he meant compiles down to javascript

christianromney00:12:08

don’t worry if you don’t know what all this means right now

christianromney00:12:17

you will eventually

christianromney00:12:33

or you do, but not in the beginner docs

bryce00:12:11

the mandatory nesting is great

bryce00:12:23

been schooling fools about sql order-of-operations for a week now

bryce00:12:34

(in SQL, AND and OR aren’t equivalent)

christianromney00:12:50

not having to memorize precedence rules is nice

christianromney00:12:01

* has precedence over + in js, ruby

christianromney00:12:31

2 + 3 * 4 is 14 not 20

bryce00:12:41

just use parens anyways, make your code reviewers not hate you for making ‘em look up precedence rules

bryce00:12:38

(defn my_band "cool doc string" [band] (println "my favorite band is" band))

bryce00:12:59

(defn FUNCTION_NAME DOC_STRING ARRAY_OF_ARG_NAMES FUNCTION_BODY)

bryce00:12:30

guessing that’s a macro around some kind of cleverness to quote stuff appropriately and transform the arg names into a let-statement

bryce00:12:25

ah, vector, not array

bryce00:12:52

cljs.user=> (type [])
cljs.core/PersistentVector
cljs.user=> (type "asdf")
#object[String "function String() {
    [native code]
}”]

christianromney00:12:08

btw gang, don’t stress if you’re not yet feeling it…there’s a lab coming up to try things in your shiny new REPLs

lostlucidity00:12:03

On the previous slide how does the function know what "band" is if "my_band" is the argument?

bryce00:12:26

neat, if you put your codes in a, say, band.cljs file you can run ‘em with planck band.cljs

christianromney00:12:28

@lostlucidity: good question, let me attempt to recreate here

christianromney00:12:05

((fn [band] (println “My favorite band is “ band) “Rodrigo y Gabriela”)

christianromney00:12:19

let’s break this down

christianromney00:12:38

(fn [band] (println “My favorite band is” band)

christianromney00:12:59

this part creates an anonymous (or un-named) function

christianromney00:12:19

nevermind the JS equiv

christianromney00:12:36

this just makes a function

christianromney00:12:41

but it doesn’t call or invoke it

christianromney00:12:12

but if you somehow managed to call this function (we’ll cover that in a sec)

christianromney00:12:23

you would pass it one argument

christianromney00:12:41

you know it accepts a single arg by looking at the argument list enclosed in square brackets

christianromney00:12:45

in this case [band]

christianromney00:12:59

this is just the name we give the argument we are passed

christianromney00:12:08

so we can use it later inside the print statement

christianromney00:12:13

(println “Hello” band)

christianromney00:12:21

the band in the println

christianromney00:12:28

is the same band we’re given above

christianromney00:12:03

to call a function we place it inside parentheses

christianromney00:12:23

(FUNCTION-TO-CALL argument1 argument2 … argument3)

christianromney00:12:13

i think the slide in question might have had a typo

christianromney00:12:42

quick poll: plz feel free to be candid….

christianromney00:12:07

i think we’re going kind of fast, but it could just be my biases 😄

lostlucidity00:12:37

" java.lang.ArrayIndexOutOfBoundsException: 5" this returned on def duos. That okay?

lostlucidity00:12:48

Thank you, Christian?

christianromney00:12:22

(def duos {:rodrigo :gabriela :ren :stimpy})

christianromney00:12:33

equivalent ruby:

christianromney00:12:55

duos = {:rodrigo => :gabriela, :ren => :stimpy}

seansellek00:12:11

(def fruit  {:red “apple” :blue “blueberry”})
(fruit :red)
=> “apple”

christianromney00:12:13

if the commas help you, feel free to add them

christianromney00:12:36

(def duos {:rodrigo :gabriela, :ren :stimpy}) ;; with commas

lostlucidity00:12:37

java.lang.Exception: Unable to resolve symbol: def in this context (NO_SOURCE_FILE:0)

lostlucidity00:12:44

java.lang.Exception: Unable to resolve symbol: def in this context (NO_SOURCE_FILE:0)

seansellek00:12:58

make sure to run def as a function (def …)

christianromney00:12:19

lists are special

christianromney00:12:29

you MUST type single quote first

christianromney00:12:36

when you are using a list to hold data

lostlucidity00:12:18

(:fee :fi :fo :fum) java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :fee (NO_SOURCE_FILE:0)

bryce00:12:26

without the single quote it’s gonna call the 1 function with arguments 2 and 3

christianromney00:12:19

in Clojure (or any lisp)

christianromney00:12:25

when you see open parens

christianromney00:12:40

it’s a function call

christianromney00:12:53

(FUNCTION-TO-CALL arg1 arg2 …)

christianromney00:12:03

the single quote

christianromney00:12:13

dude, don’t call this like a function

christianromney00:12:17

treat it as DATA

christianromney00:12:41

is just a shortcut for typing

christianromney00:12:54

try that in your repl!

bryce00:12:34

cljs.user=> '(+ 1 2 3)
(+ 1 2 3)
cljs.user=> ~'(+ 1 2 3)
undefined is not an object (evaluating 'cljs.core.unquote.call')

cljs.user=> `'(+ 1 2 3)
(quote (+ 1 2 3))

bryce00:12:37

how do i unquote?

lostlucidity00:12:33

So vectors are treated as functions?

christianromney00:12:34

(we won’t cover that yet)

christianromney00:12:45

nope vectors are like arrays

christianromney00:12:01

[1 2 3] ;; vector

christianromney00:12:32

the difference between vectors and lists (why you want one instead of the other) will be covered later

christianromney00:12:43

i’ll make sure we spend a few minutes talking about that

lostlucidity00:12:13

Okay, so the tick is needed because paranthesis?

christianromney00:12:14

@bryce unquote will be (within the context of syntax-quote) ~

christianromney00:12:35

to tell clojure “this is not intended to be a function call"

christianromney00:12:47

@bryce for unquote you could do this (this example is totally contrived btw)

christianromney00:12:45

we’ll cover unquote, backtick and macros in general in part 4 of 4

christianromney00:12:52

you’re way ahead

christianromney00:12:20

we have 4 main collection types

christianromney00:12:38

lists, vectors, maps, sets

christianromney00:12:54

'(1 2 3) ;; list

christianromney00:12:57

[1 2 3] ;; vector

christianromney00:12:30

{:fn “Mickey” :ln “Mouse”} ;; maps

christianromney00:12:54

#{0 1 2 3 5 8 13} ;; sets

christianromney01:12:19

Anyone have any questions???

christianromney01:12:57

this part is kinda advanced

christianromney01:12:16

the code on the slide is a bit hard to see

christianromney01:12:23

here’s a similar example

jorda0mega01:12:27

the :as key signals the rest of the map?

christianromney01:12:35

did we cover let already?

christianromney01:12:56

:as lets you give a name to the entire map

christianromney01:12:02

so here come some examples

christianromney01:12:18

(let [x 1 y 2] (+ x y) ;; => 2)

bryce01:12:43

an un-found destructure turns into nil

christianromney01:12:34

(let [nums [1 2] [a b] nums] (+ a b)) ;; => 3

christianromney01:12:17

(def me {:fn “Chris” :ln “Romney”})

christianromney01:12:55

(let [{:keys [fn ln] :as user} me] user) ;;=> {:fn “Chris” :ln “Romney”}

christianromney01:12:15

(let [{:keys [fn ln] :as user} me] fn) ;;=> “Chris”

christianromney01:12:03

sorry i went too fast

christianromney01:12:07

examples corrected

lostlucidity01:12:33

Why do :as when the map has a name already?

christianromney01:12:49

it may not always already have a name

christianromney01:12:56

depending on where/how you use it

christianromney01:12:01

so here’s one example

lostlucidity01:12:56

Got it!.. probably

christianromney01:12:18

this is a lot of material being covered very quickly

christianromney01:12:24

feel free to ask in this channel

christianromney01:12:31

I’m always here

christianromney01:12:00

one thing I want to tell everyone: don’t be discouraged if some of this takes a while to really sink in

christianromney01:12:06

it’s A LOT of material

christianromney01:12:13

being covered very quickly

bryce01:12:34

cond vs. case: is the only difference the syntax for the default option?

christianromney01:12:14

case does a literal match against a value

bryce01:12:26

ahhh, and cond checks for truthiness?

christianromney01:12:10

there’s also condp

christianromney01:12:19

which is somewhere in between 😄

toro01:12:26

get romantic with your clojure~

jorda0mega01:12:36

could you explain that? case vs cond

bryce01:12:55

jorda0mega: let me write some code

bryce01:12:50

(cond
test expr
test expr)

bryce01:12:03

cond evaluates each test and if it’s true, evaluates the expression

bryce01:12:24

(case some-value
comparison expr
comparison expr)

bryce01:12:00

case requires that you pass in some value, it evaluates comparisons, and if that comparison equals some-value, evaluates the expression

bryce01:12:16

(condp some-function some-value
test expr
test expr)

bryce01:12:22

condp is halfway between ‘em

bryce01:12:46

it evaluates some-value, takes that value down each test, evaluates (some-function some-value test)

bryce01:12:52

if that comes true, it evaluates the expression

bryce01:12:39

(defn band_evaluator
  "fart"
  [band_name]
  (case (get band_quality (-> band_name
                              .toLowerCase
                              keyword))
    :great (println "you like" band_name "and have taste")
    :okay (println "i agree," band_name "is okay!")
    (println ":middle_finger::skin-tone-6::santa::skin-tone-6:your opinion of" band_name "is WRONG :middle_finger::skin-tone-6::santa::skin-tone-6:")
    ))

(defn cond_evaluator
  "fart"
  [band_name]
  (let [quality (get
                  band_quality
                  (-> band_name
                      .toLowerCase
                      keyword))]
  (cond
    (= quality :great)
    (println "you like" band_name "and have taste")
    (= quality :okay)
    (println "i agree," band_name "is okay!")
    :else
    (println ":middle_finger::skin-tone-6::santa::skin-tone-6:your opinion of" band_name "is WRONG :middle_finger::skin-tone-6::santa::skin-tone-6:")
    )))

(defn condp_evaluator
  "fart"
  [band_name]
  (condp = (get band_quality (-> band_name
                              .toLowerCase
                              keyword))
    :great (println "you like" band_name "and have taste")
    :okay (println "i agree," band_name "is okay!")
    (println ":middle_finger::skin-tone-6::santa::skin-tone-6:your opinion of" band_name "is WRONG :middle_finger::skin-tone-6::santa::skin-tone-6:")
    ))

bryce01:12:56

this is how cond, case, and condp differ

bryce01:12:05

and you can see my middle finger santas get really mangled too

julian15:12:27

Great intro last night! Here are some more resources:

wcooper16:12:16

Thank you!

adrianm17:12:07

Hey guys! Just wanted to thank everyone for coming out. You were a great audience. I’m going to be sharing my slides with the group shortly. @julian Thank you for sharing those resources. I’ll be adding to that list as well.

christianromney20:12:22

Om Next will be easier to digest from this https://awkay.github.io/om-tutorial/#!/