I managed to solve a puzzle I couldn’t figure out for days! Feels pretty great. Now I’ve made the puzzle more complicated, but I’m not sure how to search for what I need. I can’t figure out how to identify whether or not a specific string is present in a vector of strings. Can anyone give me a hint on what kinds of functions I should be looking at, or the right keywords or phrases I should use to search for this myself?
check some
(string? "foo") ;=> true
(some string? [1 2 3 "foo" 4 5]) ;=> true
Thank you! Let me play around with that, see if I can make it work
Does it need to be a vector of strings? Could it be a set instead?
>how to identify whether or not a specific string is present in a vector of strings
that’s not what she said
some
with the correct predicate will do exactly what she asked
I’m not providing the right predicate of course
@bronsa Ah, gotcha 🙂 I got confused by the example…
When would you use a set instead of a vector?
Because sets are a datastructure that makes it quite easy to answer “is x in #{x y z}“, by their design.
sets are unordered and don’t allow duplicates, they can answer the question “is X in Y” in constant time
What is constant time?
it means that no matter how large the set is, the question will be answered in the same amount of time (roughyly)
as opposed to e.g. linear where the time it takes to answer the question depends on how large Y is
Vectors, by design, are “linear” in this aspect — if you have 10 million elements, you have to go one-by-one and check “is this what I want”?
(Which is what @bronsa’s example will do, behind the scenes)
generally you want to use vectors when you want to have a collection that maintains order and when you care about accessing random elements of that collection (e.g. what is the 3rd element of X), sets are used when you don’t care about order and you only care about membership (is X in Y)
BTW this is not Clojure specific at all — if you are interested in more detail there’s ton of resources out there about algorithms and data structures, the basic building blocks of all programs.
That’s really helpful, thank you! I should definitely use a set, I don’t care about order in this case.
in that case you probably want contains?
with a set
(contains? #{"foo" "bar"} "foo") ;=> true
Sets are also special in clojure in that you can treat them as functions:
user=> (#{1 2 3} 2)
2
user=> (#{1 2 3} 4)
nil
Beware that contains?
will not work with vectors the way you’d expect:
user=> (contains? ["a" "b" "c"] "b")
false
user=> (contains? ["a" "b" "c"] 2)
true
Ah…
That makes sense. Thank you!
user=> (doc contains?)
-------------------------
clojure.core/contains?
([coll key])
Returns true if key is present in the given collection, otherwise
returns false. Note that for numerically indexed collections like
vectors and Java arrays, this tests if the numeric key is within the
range of indexes. 'contains?' operates constant or logarithmic time;
it will not perform a linear search for a value. See also 'some'.
I got bit by this when I started doing Clojure — most other languages will give you something like contains?
for vectors/arrays, but Clojure will by design not, because you might accidentally slow down your program.
That’s really interesting. I do wonder if I’m having a better experience in some ways of coming to Clojure as a complete newbie than programmers who have other languages to shape their thinking. It’s taking some time to adjust to the mathematical expressions, but once I accept the new meaning of a word like ‘argument’ or ‘reduce’ that’s all there is. No competing definitions or expectations.
Yup — I’d love to read a writeup of your experiences so far. I wouldn’t suggest Clojure as a good “first language”, but perhaps the gotchas I have in mind are just irrelevant if you don’t come from a different language background.
yeah I don’t know if I’d say clojure is a good first language — it’s definitely focused on experienced users and professionals
When you say ‘it’ do you mean the language itself or the support infrastructure though?
I’ve found that to be extremely true for the latter - not so much for the former.
both
there’s languages that are significantly more beginner friendly
Such as?
in both tooling/infrastructure, guides and the language itself
racket for example if you want to stick to lisps
it’s great and intended for teaching
Actually I think that the Lisp-nature itself is quite simpler to get started with syntax. Python for example has a more “traditional” syntax that takes some time to grok if you’ve never programmed before.
I’m curious to know how did you approach Clojure — read a book, online guide?
Over the past year I’ve been to a number of introductory workshops and started studying a number of languages, including Ruby, Python and Javascript. I’ve never got very far with any of them.
I attended a ClojureBridge workshop here in London, liked it well enough, and was impressed by how inclusive and supportive the community seemed.
I attended a second workshop last Saturday, and, in reviewing the same workshop materials, things I remembered struggling over last time I breezed through this time.
by all means I’m not saying don’t use clojure as a first language btw
I’ve never experienced that with a language before.
I’m just saying it’s not the easiest first language one could pick
it’s definitely a great first language to learn, just not an easy first language
Ooh, do you remember which things you were struggling with?
Well, it’s not like I selected it and threw all my effort into it because I decided it would be the best starting point or anything. I tried a bunch of things, and Clojure was what stuck first.
One sec, I’ll check exactly what I struggled with before that was easy now…
It was collections. Drawing up vectors of maps then changing them by using conj etc.
this conversation reminds me of when I began programming, it was php...I was very confused by the fact that .
was the string concatenation operator (`str` is much more intuitive, isn't it...)
I’ve been wondering where all those full stops have come from! I’ve seen them around.
The fewer bits of punctuation lying around, the easier it is for me to read.
Another reason I like Clojure 🙂
the easier it also is to google for stuff :)
Yes, exactly!
How about immutable data structures?
there's this article which did wonders for me, begginning with clj https://yobriefca.se/blog/2014/05/19/the-weird-and-wonderful-characters-of-clojure/
Immutable data structures aren’t a problem, because I’ve never known any differently. In fact, it seems to limit the number of errors I can make.
When I was doing my master’s thesis, I was learning Python — and because I sorted a list in-place, my program was producing garbage. That took me 2 months to figure out, and I thought I’m an idiot and I’ll never be a programmer.
(I was offline for those two months, staring at the code, not figuring out what was going on)
That’s how I’ve always felt with other languages. And I’ve given up and walked away.
Mind you, I was already working professionally for a few years before that, in Java. I cannot imagine what would it be if I was trying things for the first time.
I honestly don’t know what the reason is, but something has really stuck this time. Every day since the workshop I’ve been logging on to try and fix a bit more of whatever puzzle I’ve been working on.
It’s just fun. I like puzzles, and the barrier to entry feels reasonably challenging but not insurmountable.
I’ve solved two puzzles on my own since the workshop on Saturday. It’s felt amazing.
What puzzles are you doing? I learned Clojure via adventofcode, but some might be a bit too hard.
Just continuing work on the ClojureBridge materials, though interpreting it to suit myself!
(And I got the same impression of the community — I’ve stuck around mostly because of how welcoming is everyone)
One of the exercises is ‘make a sandwich’. They have a specific way of solving it, but I didn’t like that way so I changed the question.
I decided I wanted to be able to create a list of ingredients ("bread" "cheese" "tomato")
and add “sliced ” to the front of each of them so the list would become ("sliced bread" "sliced cheese" "sliced tomato")
I’m sure it sounds really simple, but it took me DAYS
I roped in the iOS developers and platform engineers I work with, none of whom know Clojure
Just hearing and seeing how they approached it as a programming problem regardless of language was really interesting!
But eventually I solved it on my own:
(def ingredients ["bread" "cheese" "tomato" "lettuce"])
(defn slice [ingredients] (str "sliced " ingredients))
(map slice ingredients)
Basic, right? 😂 But I had fun figuring that out. It didn’t get frustrating, I just had to go through the Clojure docs, pay attention, try new things, watch it break, try more things, go through the docs again, try more things, and so on.
It hasn’t been frustrating at all, even when I’ve hit brick walls.
I’ve got so, so frustrated with the other languages I’ve tried, and very early on, too - exactly when I would expect things to be easiest and most enjoyable.
So now I’m trying to butter just the bread in that sandwich! Don’t give me the answer though, I want to work it out for myself. 🙂
Tiny nitpick — you’re reusing ingredients
in both the def
and as an argument to slice
. It hurts readability a bit, though it’s technically not an issue. I’d rename the ingredients
in slice
to ingredient
, or, in Clojure tradition, just x
🙂
Thank you!
I’m loving this conversation. Do you mind if I copy some of your quotes for a future blog post? Anonymous or Eponymous, whatever your prefer.
No, that’s totally fine, and you can use my name
I’ve been thinking of writing a blog post myself - I’m leaving my job soon and will be putting more time into this
So when using defn
I should always just use x
for the argument?
I think that functional programming with immutable data is much closer to math and can be reasoned about, whereas “mainstream” programs can be much more complex.
I’ve been struggling a bit with functions in general, so good to understand the basics a bit better in any way I can.
The maths part is what’s been hardest, in some ways - I never liked it, and haven’t studied it since I was 16.
Well, x
it’s “just” a name — you can name it whatever you want. It is valid only inside the functions (technically, its scope is the function body).
I’m not really used to logical thinking like this. I was a ‘creative’ kid, and my degree is in Japanese.
“Just” is in quotes because there’s a running joke that naming things is one of the hardest things in computer science.
Although I have noticed some parallels between Japanese and Clojure that have been pretty interesting… That I may write about at some point.
So I should name it something then? Or I shouldn’t? What’s the convention?
the convention is to use x
when it doesn't matter what the parameter is called
Clojure has a tradition of using very short names in simple functions like this. You may have seen this in the docstrings of the core functions.
Just to clarify, the suggestion is:
(defn slice [x]
(str "sliced " x))
Thank y ou!
That’s really helpful.
But this is equally valid:
(defn slice [ingr]
(str "sliced " ingr))
Sometimes you might want to give a more meaningful name when you are solving a puzzle.
This is just helping you read the program, the compiler doesn’t care.
and if you want to be able to skip naming something entirely, you can use partial
instead: (def slice (partial str "sliced "))
My initial comment was only that you had a variable ingredients
, and reusing the name also an argument in a function is risky (though also technically correct) — a typo might lead to a 2 hour pull-your-hair debugging session 🙂
there’s definitely many parallels between learning a new programming language and learning a new natural language
It’s interesting that you say it hurts readability - from my perspective right now, the more words get replaced by non-words, the extra burden I have to guess/remember when reading. So that suggests that professional Clojure code will be harder for me to read, because of the preference for shorter names or no name at all.
But with Japanese specifically, though.
use a name when it helps readability, use a generic name like x
when it doesn't 🙂
For example, there are particles in Japanese that almost directly map onto def and let. I understood the concept of global and local scope immediately because of it.
interesting :) I don’t know japanese so I couldn’t tell
that’s super interesting
I would read a blog post about it
You’re not the first to say that! Once I’m out of work I think I’d like to write one.
for example, the parameter for inc
i s named x
, because naming it number
wouldn't really help much
Why wouldn’t it?
I have to side with Amelia on this one — the single letter parameters can be a bit too much some time, esp. if you are in unfamiliar territory.
one thing that I’ll suggest to a complete beginner (feel free to ignore my advice if you think trying to learn too many things at once would be too much) — would be to not focus so much on learning a new language as much as learning the algorithmic way of thinking. this is one of my biggest issues with e.g. clojurebridge or http://code.org where they give the language a bit too much focus IMO studying something like https://mitpress.mit.edu/sites/default/files/6515.pdf would be what I’d suggest a beginner do first — and then learn a particular language
well, at least to me - number
doesn't add any value over x
, since inc
already means 'increment a number`
I take your point, but it does raise the barrier to entry.
so there's no need to specify
Right now I’m having fun solving puzzles
Once I get to a point where I feel like I’d like to continue solving puzzles and be able to solve more complicated puzzles, that seems like the right time to seek out more knowledge
i think it's better to name things only when that name adds value
I do know what you’re saying, not least because I saw this in Japanese too - people jumping in and learning through experience struggled to get to my level of fluency without the benefit of a rigorous education in grammar.
but of course, this is a matter of taste :~)
yep that’s completely understandable — it’s just that I’ve seen way too many people going down that route and hitting a point where the lack of training in “algorithmic/abstract thinking” makes them hit a brick wall
I can see that, for sure
so keep this in mind when you’ve advanced a bit
@sundarj of course, the docstring for inc
refers to “num” while the parameter is named x
:
clojure.core/inc
([x])
Returns a number one greater than num. Does not auto-promote
longs, will throw on overflow. See also: inc'
As things stand, I’m approaching coding very similarly to the way I approached Japanese. I probably spent about a year learning the pretty alphabets and writing out song lyrics just for fun, then when I realised I wanted to commit to serious learning I applied for my degree.
hah, guess they changed the param but forgot to change the docstring
Or the other way round? 🙂
I can’t do another degree, but I can certainly see the value both in some early experience-based learning to build up an appetite for more rigorous study of fundamentals, and the study itself.
possibly 🙂
BTW, I’m going through the ClojureBridge curriculum — it’s very well done. @amelia do you use Nightcode?
I do now!
i know Japanese to an intermediate level (it's my favourite natural language by far), curious which particles you're referring to
Though I’ve just been using the REPL on the workshop pages for the puzzles I’ve been working on
は (global scope) and が (local). :)
Not a direct relation, as the wa can be replaced by another wa at any time, but it was enough to help me grasp the concept of global vs. local.
ooh, that's neat! i've never thought about them like that before 🙂
Good good — I might sign up for ClojureBridge to help with any upcoming event in my area 🙂
I need to go back to actual work now though…
i do love thinking about the connections between linguistics and computer science
I’ve also been thinking about the concept of kanji compounds as immutable data structures, with the attached verb endings the equivalent of functions, but I’m not sure yet how precise that is!
Me too 😂
I’m a bit obsessed at the moment, I just want to spend all day playing with Clojure…
interesting!
did you know there's a programming language called Perl that was created by a linguist? its design is informed by linguistic principles, which i think is pretty neat
Been there 🙂
thinking about this some more, using a function with map
is like using a verb with すべて