(For anyone needing an excuse to procrastinate.)

Is this a very julian way to write this? How could it be improved?

``````function fizzbuzz(i, ps)
s = [p.second for p in ps if p.first(i)] |> join
return isempty(s) ? string(i) : s
end

ps = ((i->i%3==0) => "Fizz",
(i->i%5==0) => "Buzz")

fizzbuzz.(1:20, Ref(ps))
``````
2 Likes

Hereâ€™s a prosaic version I might write in â€śreal codeâ€ť:

``````function fizzbuzz(i)
f = i % 3 == 0
b = i % 5 == 0
f && b ? "FizzBuzz" :
f      ? "Fizz"     :
b      ? "Buzz"     : string(i)
end

for i in 1:20
println(fizzbuzz(i))
end
``````

Arguably this has the benefit of being straightforward, keeping the logic related to fizzing and buzzing in one place, separating the side effects, and not allocating more than â€śnecessaryâ€ť (maybe could be better in that way if we went direct to `IO`). It has the downsides of being boring and not generalizing to arbitrary predicates

7 Likes
``````ps = ((i->i%3==0) => "Fizz",
(i->i%5==0) => "Buzz",
i->i%7 ==0)=>"Zap")

function fizzbuzz(n,ps)
res = ""
for (key,value) in ps
if key(n) == true
res *= value
end
end
if res == ""
res *= string(n)
end
return res
end

julia> for i = 1:21
println(fizzbuzz(i,ps))
end

1
2
Fizz
4
Buzz
Fizz
Zap
8
Fizz
Buzz
11
Fizz
13
Zap
FizzBuzz
16
17
Fizz
19
Buzz
FizzZap

``````
2 Likes

maybe using a function to access the values rather that accessing the field directly?

``````s = [last(p) for p in ps if first(p)(i)] |> join
``````
1 Like

Yes, this is boring. But I looked at my code less than 24 hours after writing it and didnâ€™t immediately understand it! So maybe boring is not such a bad thing.

Also, good point about removing allocations.

4 Likes

Thanks. As far as I can see this is essentially the same `fizzbuzz`, except it avoids creating an array of strings. Is that the point here?

I just wanted to do my own version , but there are esencially the same, as they use the same arguments.

1 Like

Just realised the array allocation

``````    s = [p.second for p in ps if p.first(i)] |> join
``````

can be replaced with a generator.

``````    s = join(p.second for p in ps if p.first(i))
``````

Itâ€™s faster too.

1 Like

Iâ€™m so lazy hereâ€™s how Iâ€™d probably write itâ€¦

``````FizzBuzz1(x) = ( (x % 3 == 0) ? "Fizz" : "") * ( (x % 5 == 0) ? "Buzz" : "")
FizzBuzz1.(1:30)

FizzBuzz2(x) = reduce( *, ["Fizz","Buzz"][(x .% [3,5]) .== 0])
FizzBuzz2.(1:30)
``````

Awkward looks like I just failed my code interview! Hereâ€™s a quick monkey patchâ€¦

``````function IfNothingThenX(fn, x)
result = fn(x)
return ( length(result) == 0 ) ? x : result
end

IfNothingThenX.(FizzBuzz1, 1:30)
#Or...
IfNothingThenX.(FizzBuzz2, 1:30)
``````
1 Like

The `reduce` version gets my vote!

1 Like

Right! I feel itâ€™s an uncomfortable fact that boring is often great for maintenance. Thought provoking reading: Dan McKinley :: Choose Boring Technology

6 Likes

Boring is usually the best for maintenance! Often good for performance too. People who write languages, write them to be used pragmatically (usually).

I have a proclivity to solve small units of code as quickly as possible. Sometimes it bites me, sometimes it saves me a bunch of trouble because 70% of it goes to the garbage heap or the metaphorical â€śnever to be touched againâ€ť code file.

An ironic suggestion on the Julia mailing list

I was working at Etsy with Dan (author of that blog post) when Kellan became the head of engineering. The effort to get rid of miscellaneous â€śexcitingâ€ť technology was clearly the right thing to do. We did not need web services built in Clojure in company where most things were written in PHP. We also didnâ€™t need MongoDB for one service when other things were all backed by MySQL.

However, at one point Kellan tried to convince me that it would be better to write a recommender system in PHP. And thatâ€™s where things become less clear cut. Could you write code that computes SVDs of sparse matrices in PHP? Honestly, I donâ€™t know. For that application, PHP becomes an exciting technology rather than a boring one. You know whatâ€™s a boring technology for building a SVD-based recommender system? Matlab. So thatâ€™s what I used. Unfortunately, that entails deploying Matlabâ€”fortunately not for serving recommendations, we precomputed those and stored them in MySQL to be served from PHPâ€”but we did deploy Matlab for generating new recommendations each day;
not a critical component since when it failed all that happened was that recommendations didnâ€™t get updated, but still unpleasant and risky. Deploying Matlab is back in rather â€śexcitingâ€ś territory again. However, that seemed like the least exciting option available at the time.

That was in 2010, and Julia was just a weird side project that everyone made fun of me for working on in my spare time. (Having your own programming language is the tech equivalent of having your own religionâ€”people back away slowly when you start to tell them about it, until it becomes well known and then itâ€™s cool, I guess?) If it was today and I needed to build and deploy such a recommender system, Julia would be a nice boring technology for that. Python would also be a fine and arguably even more boring technology for it. Deploying Julia is, in any case, way more reasonable and boring than deploying Matlab was.

I think the bottom line is that you have a certain amount of novelty budget for an endeavor, so think hard about where you want to spend it and what you get in exchange.

38 Likes

Haha! The irony was not lost on me was partly lost on me due to being several levels deep, thanks for the story! By the way I really do like that blog post but it makes me strangely uncomfortable at the same time. Perhaps itâ€™s the problem of being a research scientist who knows enough systems engineering to be dangerous (or is it the other way aroundâ€¦ Iâ€™m never quite sure anymore )

Having a novelty budget is a good way to think about the problem.

6 Likes

This rings familiar from a developer and team lead perspective.

1 - weâ€™ve been using PHP for over 10 years. Itâ€™s the least exciting language, almost as uncool as your neighbourâ€™s 1997 Prius. However, it just works. The upgrade path from PHP 5 (or was it 4 when we started?!) to current 7 was simple and cheap. And you get very good performance with minimum tweaks (99% of the time the RDBMS is the bottleneck).

2 - however, there are things that a language will just be bad at, up to the point where itâ€™s just not worth optimising for that. For us, it was processing very large amounts of XML data with PHP in real-time. We ended up choosing Go, but it was part of that research that I discovered Julia (Julia was just too young at that point, it mustâ€™ve been 0.4). We ended up with a pretty efficient services architecture in PHP and Go.

3 - as a developer, getting to work with new technology is fun and exciting and as the team lead I see this as a reward for the team. But as a team lead/CTO one must very thoroughly weigh that against the fact that youâ€™re adopting new languages which need expertise, recruiting, training, etc for long term maintenance. If your only Go dev leaves, you need to find a solution fast. So once you adopt a language, best to adopt it for a wide class of projects and tasks and understand that youâ€™re committing to that language.

9 Likes

With some coauthors, we are nearing a milestone (an actual draft of preliminary results, yay ) of a medium-sized numerical project (solving a particular model), so at some point I will be tempted to write up a similar account of our experience for scientific computing, particularly in Julia, because we have a nice trail of benchmarks from the very beginning to a more than 100x speedup using various tricks (so now the runtime is just 2 days ).

The most important lesson at this point is to get one working version of the whole computation stack before any algorithmic or optimization. This is mentally difficult to do, because we all know that whatever ends up there will be completely rewritten N times (currently, at least N = 6 for us) so it all seems like wasted effort. But without something to profile and benchmark, we would probably misallocate our â€śoptimization budgetâ€ť.

The unexpectedly nice thing about Julia is how easy it is to write â€śloosely coupledâ€ť code that can be optimized and benchmarked in small pieces. So, we can experient with replacing a `Vector` with a `StaticVector`, or allocating in an object pool for some parts, or switch AD libraries, pretty much without rewriting anything else. This in itself makes up for the wholes in the ecosystem.

18 Likes

Not strictly related but just a delightful rant form Dan about even earlier days at Etsy than I was there for:

Part of the moral of the story is that even though Python + Twisted is a perfectly boring technology, boringness is context dependent: as a middleware later in a PHP stack, Python is totally unnecessary.

7 Likes

39 posts were split to a new topic: Code-golfing FizzBuzz