Fork me on GitHub
#beginners
<
2016-01-10
>
plaxdan02:01:22

The first example of (do…) at clojuredocs states: > do is used to evaluate multiple expressions in order, usually for the purpose of evaluating exprs that have side-effects (such as printing or I/O). do returns the value of its last expression. https://clojuredocs.org/clojure.core/do#example-542692cfc026201cdc326e9f Why group the expressions with do? Why not just list the expressions. E.g. what is the advantage of doing this:

=> (do
     (println "LOG: Computing...")
     (+ 1 1))
…over just doing this:
=> (println "LOG: Computing...")
   (+ 1 1)

akiva02:01:01

@plaxdan, those are equivalent—they both return 2—but you can’t do the second in a let binding, for example.

akiva02:01:54

do is good for whenever you want to bind up multiple sexps, with all but the last returning an actionable value, in situations where multiple sexps can’t be used.

akiva02:01:15

Another example is when you want to have multiple sexps in an if branch.

akiva02:01:49

Or any cond really.

plaxdan02:01:44

Thanks for your reply. I’m still missing something. Perhaps the (possible) wrongness of my example above will point out what I’m missing? Also what’s a “sexp” …side-effect-expression?

plaxdan02:01:48

OK I think I know what you mean now...

plaxdan02:01:53

The example above would not be possible without the do. I suppose I’ll come across a real-world usage at some stage.

plaxdan02:01:16

I’ve no idea why someone would put a sexp in a let, if, or cond though.

meow03:01:56

@plaxdan: What's an sexp? (I'm using the Socratic method to help you)

plaxdan03:01:36

I guessed that it was side-effect-expression and the confirmed it with the goog.

plaxdan03:01:48

So it’s not purely: "an expression which yields a side-effect”?

plaxdan03:01:48

Thanks for the link. So it seems that everything in Clojure is a sexp.

meow03:01:34

now tell me how if works in clojure

plaxdan03:01:36

Maan I was so wrong simple_smile

plaxdan03:01:05

Well regarding if.

plaxdan03:01:13

It is a function expressed as a sexp which expects 1 or two arguments each of which is also expressed as a sexp.

plaxdan03:01:34

OK that sucked.

plaxdan03:01:36

Let me try again.

plaxdan03:01:49

- If is a function expressed as a sexp (since all of clojure is expressed as sexps) - the first argument is a sexp which is evaluated for its truthiness - when the first arg is truthy the second argument is evaluated and returned from the function - when falsey the (optional) third arg is evaluated and returned from the function

meow03:01:54

(doc if)
-------------------------
if
  (if test then else?)
Special Form
  Evaluates test. If not the singular values nil or false,
  evaluates and yields then, otherwise, evaluates and yields else. If
  else is not supplied it defaults to nil.

  Please see 
=> nil

plaxdan03:01:55

It’s so cool that if is a function with docs like any other.

plaxdan03:01:24

I missed the part about returning nil should then evaluate as falsey and no else being supplied.

meow03:01:44

are there really functions in clojure?

meow03:01:08

or just objects that implement the IFn protocol?

meow03:01:38

might be more meta than you are ready for, but what the heck

plaxdan03:01:08

Haha no that’s fine, I really appreciate you being willing to even discuss it like this. Thankful the #C053AK3F9 channel exists! It seems like you’re reminding me to conceptualize a Clojure program as simply the tree-shaped data literal that it is.

akiva03:01:05

If @meow has no Buddhist training, I’d be pretty surprised based on this conversation.

meow03:01:10

back to if - what do you do if you want more than one thing to take place within the truthy branch

meow03:01:41

@akiva: nothing formal simple_smile

plaxdan03:01:59

You group them into a single sexp

akiva03:01:15

@meow, you’re on fleek, as the kids like to say.

akiva03:01:34

Anyway, you two go on. I’m going to sit back and watch and no longer interrupt.

plaxdan03:01:08

With either a let, another if or something else like /drum roll pls/ do?

meow03:01:20

this reactji performance art was brought to you by https://twitter.com/DalaiLama

mfikes03:01:44

What about the concept of if being a function? Can you pass it to a function as a value?

mfikes03:01:07

Can you do (def foo if)?

mfikes03:01:38

Or, even simpler, what if you simply type if at a REPL to see if it can be evaluated, like, say, other functions like map or filter?

plaxdan03:01:27

@mfikes: it would appear not!

mfikes03:01:41

if is kind-of special simple_smile

meow03:01:05

@mfikes: is that why the source code link for if on clojuredocs is fubar? https://clojuredocs.org/clojure.core/if

mfikes03:01:12

In ClojureScript there are 20 such special things. (Probably a similar number in Clojure.)

mfikes03:01:07

Well, you can’t do (source if)

meow03:01:37

I've never tried to look at how/where it is handled

meow03:01:24

@plaxdan: tell me how a clojure keyword is special

plaxdan03:01:04

So ^“on fleek” is one of those cromulent words it seems.

plaxdan03:01:38

> tell me how a clojure keyword is special pondering….

plaxdan03:01:00

It seems that a keyword is a pointer to another part of the sexp tree?

mfikes03:01:04

The 20 in ClojureScript comprise { var, if, case*, throw, try, def, fn*, letfn*, do, let*, loop*, recur, quote, new, set!, ns, deftype*, defrecord*, ., js* }

mfikes03:01:57

That’s all there really is, at the bottom. simple_smile

mfikes03:01:29

A keyword doesn’t really point to anything.

meow03:01:42

I thought it was turtles all the way down

mfikes03:01:02

There are 20 special turtles at the bottom

plaxdan03:01:34

OK you are meaning keyword to be the ones in that set where I was considering those that may be created by the programmer as well. So now the question: what’s special about those in the set above..?

meow03:01:40

are you familiar with keywords in clojure?

mfikes03:01:44

Well, you have things that are types of values, 1 is a number, :foo is a keyword, ”abd" is a string.

plaxdan03:01:33

@meow: I do. My response earlier demonstrated that I often conflate keywords and symbols.

mfikes03:01:34

The special forms are not values. David Sletten pointed out that some people like to pendantically refer to them as special operators

mfikes03:01:59

Operators because of where they go.

plaxdan03:01:15

So keywords are those prefixed with a colon … :as, :else etc..,

meow03:01:23

@mfikes: are they just recognized by the reader and handled as special things?

mfikes03:01:32

In other words, (if true 1 2) can be thought of as a form, but if is in operator position.

mfikes03:01:54

But special form is what things like if are usually called.

meow03:01:08

@plaxdan: right, now how can a keyword be used

mfikes03:01:47

@meow: Special forms are definitely in the analyzer. (Not sure about the reader—that’s a good question.)

meow04:01:30

I've yet to dive into the whole code reading/analysis process

meow04:01:38

in clojure

plaxdan04:01:27

It seems that the keyword is used to mark a subtree of the sexp tree for special keyword-dependent contextual interpretation. A delimiter.

mfikes04:01:56

@meow: What is profound, is that the analyzer essentially only works in terms of special forms, in a sense, and the compiler emits things that the analyzer puts in the AST. Everything else is a glorious abstraction on top of that, mostly sitting in cljs.core, etc.

meow04:01:17

moar meta

mfikes04:01:26

Yep. Maxwells equations.

mfikes04:01:57

(Referring to Alan Kay, referring to John McCarthy’s stuff.)

meow04:01:11

plaxdan: none of those words resonates with me - they might be correct - let me ask it differently

meow04:01:00

can you give me an example of how you might use a keyword

mfikes04:01:03

Yeah, for one thing, a keyword evaluates to itself

mfikes04:01:19

(Like a string or a number.)

meow04:01:34

identity fleek

meow04:01:04

I don't know how keywords are handled by clojure

meow04:01:48

kind of like a generic special form

meow04:01:58

but I don't know where or how

meow04:01:04

I know you do, mike

plaxdan04:01:37

@meow: where an unpredictable number of prior sexps in a list exists? If the number of prior sexps in a list was interpreted in a fixed way then you wouldn’t need a keyword? Example: if expects 2 or three so no keyword would be necessary since they can be interpreted by their position Example 2: cond may expect any number of sexps and therefore a keyword must be used as a marker.

plaxdan04:01:48

…the :else keyword in that case.

meow04:01:24

ah, I see

meow04:01:40

erase that from your mind for a moment and go moar meta

meow04:01:45

what is a keyword

meow04:01:59

independent of the if function

meow04:01:16

like, what is a string

plaxdan04:01:22

It is a name that points to itself?

meow04:01:33

and what can you do with it

plaxdan04:01:45

Guarantee its uniqueness in the context of your code?

mfikes04:01:03

keywords are not a special form

meow04:01:20

right - just meta thinking out loud

meow04:01:27

they are a type, yes?

meow04:01:40

or not - what are they mike?

plaxdan04:01:41

Yes they are a type.

plaxdan04:01:12

They are not strings or anything else other than themselves so I suppose they must be a type.

mfikes04:01:29

At least in ClojureScript: deftype* is a special form.. and Keyword is a type defined in cljs.core. What’s cool is you can see how it works: It is written in Clojure/Script. simple_smile

meow04:01:59

@plaxdan: explain this

({:foo "bar"} :foo)
=> "bar"

plaxdan04:01:58

That is a map (which implements IFn).

meow04:01:01

oh wow, an actual deftype - cool

plaxdan04:01:13

Being called with the keyword :foo as an arg.

meow04:01:33

so a map is what?

meow04:01:21

nevermind, missed your previous msg

plaxdan04:01:30

A type which satisfies the IFn protocol

meow04:01:35

ok, now this:

(:foo {:foo "bar"})
=> "bar"

mfikes04:01:42

Flip it around. simple_smile Cool.

plaxdan04:01:30

Yep same thing except based on what @mfikes said earlier this is a demonstration of the Keyword type satisfying the IFn protocol and being called with the map as an arg.

mfikes04:01:09

You can see that it literally turns in to get simple_smile

meow04:01:24

so does clojure have functions

mfikes04:01:35

Hola mr Gallagher simple_smile

pragsmike04:01:53

good evening folks

plaxdan04:01:01

Hmm…I was about to say that it has types that satisfy the IFn protocol and that we refer to this subset of types as functions….

mfikes04:01:05

I see no function in { var, if, case*, throw, try, def, fn*, letfn*, do, let*, loop*, recur, quote, new, set!, ns, deftype*, defrecord*, ., js* }

plaxdan04:01:24

…but that implies that anything that can satisfy any protocol could be referred to a function.

meow04:01:37

interesting

mfikes04:01:15

There is a special form fn*

meow04:01:42

but that's more like a constructor

meow04:01:48

what does it return

mfikes04:01:48

The analyzer will spit out a bit of AST which has :op :fn key-val pair.

plaxdan04:01:16

Unless of course all protocols are derived from IFn in which case the former statement would be true.

plaxdan04:01:52

The former statement being: > anything that can satisfy any protocol could be referred to a function.

meow04:01:04

moar meta - does it really matter, so long as you can write cool code

plaxdan04:01:12

Haha NOPE!

plaxdan04:01:27

But also yes, because you enjoy it more that way.

plaxdan04:01:05

So is it true that all protocols derive from IFn?

meow04:01:21

you tell us

meow04:01:39

mr fikes gave us plenty of links to code to look at

meow04:01:20

of clojurescript, mind you

mfikes04:01:36

When you say IFn are you talking about a Java interface, or a Clojure protocol?

mfikes04:01:17

(In the ClojureScript links, IFn is a Clojure protocol.)

plaxdan04:01:21

I am talking about a clojure protocol.

plaxdan04:01:32

Would be equally appropriate for CLojureScript

meow04:01:38

what is a clojure protocol

plaxdan04:01:37

So I am learning that Clojure is a teasing apart of concepts that are bundled together in other languages. Types and protocols are examples of this.

plaxdan04:01:53

In some other languages the protocol is a type.

plaxdan04:01:31

You cannot separate them. I do not know for sure yet if it is the case that they are fully separate in Clojure but I suspect that might be the case.

meow04:01:27

so if you wanted to create a github org that captured the essence of what you just described you would name it?

plaxdan04:01:55

Hmm…I’m not sure I understand what you’re getting at but…a name that implies a set of atomic elements. Perhaps I’d name it alchemist or something.

plaxdan04:01:33

I will look at that. Going back to your earlier question: “What is a protocol?” It is a contract for behavior.

plaxdan04:01:03

That zero or more types can may satisfy.

mfikes04:01:35

There’s also the odd thing that you can have nil satisfy protocols

plaxdan04:01:50

Is not nil a type?

mfikes04:01:21

Perhaps it is the only value of the type that that value is

meow04:01:43

in python it was a singleton of something, I forget

plaxdan04:01:50

It is a set of one.

mfikes04:01:51

Unit type?

meow04:01:58

in python everything is much more reified than clojure

meow04:01:41

but python is written in C, so...

mfikes04:01:26

One interesting thing I learned recently, you can have things that satisfy nil? that are not identical to nil. (At least in ClojureScript.)

meow04:01:36

(type nil)
=> nil

meow04:01:50

oh, like what

mfikes04:01:06

In a ClojureScript REPL, if you do (def x)

mfikes04:01:18

Then ask questions about x

meow04:01:38

and what about declare, or is that basically the same

meow04:01:57

creates a pseudo nil

mfikes04:01:59

(identical? nil x) and (nil? x)

mfikes04:01:23

(I think this is perhaps the JavaScript host leaking through, where you have null and undefined which ClojureScript puts into the same equivalence class, I suppose.)

meow04:01:42

clojure:

(identical? nil x)
=> false
(nil? x)
=> false
(identical? nil nil)
=> true
(nil? nil)
=> true

plaxdan04:01:09

I feel like I struck a rich vein of gold here tonight. Thank you @meow and @mfikes .

plaxdan04:01:20

Some of that sweet internet gold.

mfikes04:01:28

It’s great dwelling on this stuff simple_smile

meow04:01:46

(declare y)
=> #'user/y
(identical? nil y)
=> false
(nil? y)
=> false

meow04:01:11

@plaxdan: that was great fun

plaxdan04:01:52

Yes. It was! simple_smile

mfikes04:01:29

@meow: I had asked Nolen about the diff between ClojureScript and Clojure regarding (def x). Ideally they’d be the same, but ClojureScript doesn’t go so far as to reify the concept of someting being “unbound”, and there hasn’t been enough payoff to do anything about it.

plaxdan04:01:29

Goodnight!

meow04:01:31

@mfikes: I'm so glad you were able to join in.

meow04:01:52

I needed that. Pure fun.

mfikes04:01:20

I enjoyed it. These concepts are not at all crystal clear in my mind… worth ruminating. simple_smile

meow04:01:38

the teacher is always the student

pragsmike04:01:55

explaining to other people always shows me that i don't really know something that i thought i did

mfikes04:01:05

Unless you are Sting, and you become the Master.

mfikes04:01:39

Or a face of alabaster or some such.

pragsmike04:01:43

it's becoming more fun to read cljs source code

pragsmike04:01:23

i'm learning that clojure/script is not really much like common lisp, except superficially

mfikes04:01:31

I think I’ve read more ClojureScript than Clojure now, by a factor of 5 to 1 at least.

pragsmike04:01:59

in CL keywords are really just symbols in a magical package

mfikes04:01:36

Hmm… I guess you could use quoted symbols in Clojure if there were no such things as keywords

pragsmike04:01:37

CL is full of things like that that were bolted on

mfikes04:01:59

('a {'a 1}) works just fine

pragsmike04:01:08

but clj designed in ways to do things better from the start

pragsmike04:01:52

i'm glad i found this community, i'm learning so much just by reading scrollback

pragsmike04:01:12

but i spend so much time reading all the links i don't get much real work done simple_smile

pragsmike04:01:02

@mfikes: do you have much interest in nodejs?

pragsmike04:01:04

bedtime, good night all

mfikes04:01:25

Ahh, yeah, getting around midnight ET US

meow05:01:08

would be cool if someone could capture that session and archive it somewhere

Tim19:01:50

how do you set up nrepl to interact with already running programs like a web server or something, so you can rewrite functions and insert println so that you don't have to restart the server? This is for development, nothing fancy like for production or something

Tim19:01:27

or I guess something like figwheel for non-browser stuff

Tim19:01:45

link to a blog post or resource would be helpful

jonahbenton20:01:00

@tmtwd: Stuart Sierra's reloaded workflow is a common starting point for working at the repl in a Clojure project: http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded

jonahbenton20:01:32

no need to set up nrepl explicitly, just running lein repl will give you a repl for your app.

jonahbenton20:01:47

suitable for development

jonahbenton20:01:40

to be able to connect to a running app that you don't have the freedom to stop and restart at will, the instructions that come with nrepl: https://github.com/clojure/tools.nrepl having your app do (use '[clojure.tools.nrepl.server :only (start-server stop-server)]) (defonce server (start-server :port 7888)) will cause it to open a socket on the specified port

jonahbenton20:01:18

to which you can connect using lein repl :connect 7888 or with an app called reply: https://github.com/trptcolin/reply