Fun One Liners

that where i saw it!

The complex step derivative is highly useful because it’s computationally very cheap, for my needs it is an extremely elegant solution - I don’t need derivatives of all functions forever, just special cases. Lots of people are using it in a variety of fields for that reason alone. I’ve been using it for certain tasks for about 4 years now across a variety of languages.

Here’s a fun one:
Make a bernoulli distributed random array.

"""
    rbinomial( p, size... )

Makes an N-dimensional array of size(s) `size` with a probability of being a 1 over a 0 of 1 `p`.
"""
rbinomial( p, size... ) = map( x -> ( x < p ) ? 1 : 0, rand( size... ) )

Source: https://github.com/caseykneale/ChemometricsTools.jl/blob/master/src/InHouseStats.jl

3 Likes

Although people are using your method often, ForwardDiff seems to be faster as well as more accurate. And, as mentioned before, it is applicable to a wider class of problems:

julia> @btime y2 = ComplexStepDerivative.(cos,x);
  9.012 μs (6 allocations: 1.98 KiB)

julia> @btime y1 = ForwardDiff.derivative.(cos,x);
  4.315 μs (6 allocations: 1.98 KiB)

julia> sum(abs2,y1.+sin.(x))
0.0

julia> sum(abs2,y2.+sin.(x))
3.998230564547902e-31

3 Likes

I simply don’t understand why one would be using it in a language that has a super-robust implementation for univariate AD already (ForwardDiff.jl) that is computationally also cheap, and arguably at least as elegant, and of course more accurate

…and an even more elegant source-to-source AD (Zygote.jl) in the works.

This is like saying that you found a nice approximation to e^x that is ok for small x, when you have exp built into the language.

3 Likes

@fabiangans - I’m glad to hear this. Trust me, my intent at posting “Fun One Liners” is not to demerit the work done by others across the Julia language by claiming superiority in a solution… Believe it or not, the intention of this thread is to share “fun one line” solutions to problems. Not “the worlds most optimal solution to a problem that definitively surpasses all available libraries in performance and robustness in one line”. It’s really about having “fun”.

If you’re interested why I am preferring to use this in my in-the-works package here’s why: for my use case, 4/100 microseconds at execution time is beyond negligible compared to requiring a dependency be downloaded, installed, and precompiled, then imported for every use. This is largely because in my experience I’ve had functionality break when using other’s dependencies, and I can learn more when writing it. I’m especially more motivated to lean towards this when one line of code solves my problem.

@Tamas_Papp - No that comparison is not equivalent. As of Julia 1.00 ForwardDiff is not built into the language. it is an external package. All that aside, this is a conversation is a bit of a derailment of the intention of this post - to have fun writing code in Julia. This isn’t a merge request to Base Julia. I’m just trying to share and learn fun things you can do easily with Julia. More importantly @Chris_Foster already shared the library for doing this with benchmarks - no passerby should be confused…

To keep things on track…

#Pattern for making lists of pairs
zipper(a,b) = a .=> b

Ex: zipper([ :a,:b,:c ], [1,2,3])

1 Like

Does the notion of this thread deeply disturb Julia programmers?

If so just delete it. I thought it would be a fun way to engage the community and learn new things - but maybe this idea is not really welcome here. If so by all means delete this thread. I’ll report this post so an admin can find it.

The fact that people disagree with you about what constitutes useful and robust code does not mean that they are “disturbed” by what you wrote… just that they disagree with you.

I am aware that some people are fascinated with one-liners, and perhaps even evaluate the “power” of a language based on how much you can do in one line. But that metric is not really useful for Julia, nor does it make your code elegant or cool — occasionally, quite the contrary.

I don’t see why this topic should be deleted. Please note that this would also throw away the effort of all those who contributed to this discussion.

3 Likes

I agree that this is a worthwhile, while lighthearted, topic. And the complex step derivative makes a fun one-liner, which is fine to post here.

I think it’s still reasonable to argue that you should not be using it in a package, because that’s not the place for ‘fun one-liners’.

1 Like

Did I ever claim the code in here should be robust? No.
Did I ever claim we should evaluate a language’s power by one-liners? No.
Did I claim elegance in one solution? Yes.

Elegant: (of a scientific theory or solution to a problem) pleasingly ingenious and simple.
Let’s compare:
Method A: User ForwardDiff
https://github.com/JuliaDiff/ForwardDiff.jl/blob/master/src/derivative.jl -> 89 Lines
https://github.com/JuliaDiff/ForwardDiff.jl/blob/master/src/dual.jl -> 609 lines
(we can ignore the boiler plate stuff)
Download -> Install -> Import -> Use -> Run

Method B: Use the One Liner
Complex Step Derivative -> 1 line
Type -> Use -> Run

Method A & B work for my use case. I’ll say Method B is therefore a measurably more elegant solution to my problem.

I’m just trying to figure out if the issue here is having fun or not. I’d rather not waste my time trying to have fun with people who are more interested in something else.

In my package I need derivatives of arcs, parabolas, and straight lines. Rather then bloat it with dependencies I am preferring to use a solution I know works roughly ten orders of magnitude beyond the precision I need in these use cases…

1 Like

OK, that’s up to you. I’m just saying that there are two very different discussions here. One of them is “what’s a fun one-liner?” (discussion 1), and I think your complex step derivative should be entirely uncontroversial in that context. But when it comes to building packages, that’s an entirely different context (discussion 2), so I think you should not be that upset if someone argues against its use there.

I think you are a bit upset that people are getting too serious in “discussion number 1”, while you should rather view it as “discussion number 2.”

4 Likes

I don’t think upset is the right word. More annoyed that people would presume I’m an ignoramus and am making a bad design decision in something they have no context for understanding… The fact that people would rather pursue something tangential and negative really defeats the spirit of this.

If it didn’t happen in the first 20 posts I’d say there was a point to this. Unfortunately, I’ve been on the internet long enough to know this thread has been ruined by derailment - as intended. I had fun at least.

I saw this yesterday by @sdanisch:

julia> topdir = "."

julia> [joinpath(dir, fname) for (dir, subdirs, fnames) in walkdir(topdir) for fname in fnames]
746-element Array{String,1}:
 "./.gitignore"                                         
 "./.travis.yml"                                        
 "./LICENSE.md"                                         
 "./README.md"                                          
 "./REQUIRE"                                            
 "./appveyor.yml"                                       
 "./scratch.jl"                                         
 "./.git/COMMIT_EDITMSG"                                
 "./.git/FETCH_HEAD"                                    
 "./.git/HEAD"       
...

Generators and array comprehensions can often pack quite a lot of power in one line.

15 Likes

Maybe you just hit a nerve here. Julia programmers are obsessed about efficiency and code sharing (one of the nicest side-effects of multiple dispatch).

Following the DRY principle, stuff which is needed in different projects will be put in a dedicated library so it has its own home and is ready to be reused.
A one-liner – which was intentionally shrunk to one line – does not fill any gap in code organisation in this sense; if it’s something handy and you want to use it in different projects, it should be part of a library, but then the number of lines really does not matter at all. ForwardDiff has the better implementation in many aspects, so that should be used when considering an external dependency (while supporting the community at the same time).

Whatever, I suggest we conclude that “ComplexStepDerivative” is not-so funny for a few of us :wink:

Blahblah, I should contribute something… :thinking:

OK, this is my favourite one liner which I use when doing some introduction to Julia (multiple dispatch 101), it’s easy to remember and not worth to be put in a library:

f(x) = 2x
3 Likes

i’m gonna put an argument favoring a complex step derivative:
lines to implement a AD with complex step derivative: 1

i’ts not the best, it can error a lot, just one variable,but is one line!

My reading of this thread is quite different from yours, @anon92994695. I don’t see folks being disturbed or even nerves being touched. I see a bunch of people excitedly contributing to the topic you started on three fronts — some are contributing new one-liners, others are suggesting improvements and changes to one-liners that have already been posted, and one person is pushing back on the idea of one-liners as an end unto themselves.

Looking at that great diversity and coming to the conclusion that “Julia programmers find this thread disturbing” and wanting to delete it is rather confusing to me. Heck, there’ve been over 70 :heart:s given out amongst the 34 posts so far! So as a moderator I’m inclined to keep it — there’s definitely a place for fun one-liners here!

21 Likes

atexit(() -> run(Base.julia_cmd()))

20 Likes

Maybe one should include the time required to do using ForwardDiff into the comparison? If one has a nice analytic function with a complex implementation already, then, depending on what you want, ComplexStepDerivative can be better than adding a dependency to ForwardDiff.

1 Like
Base.display(f::typeof(exit)) = f()
12 Likes

Try variant is a bit more effective :stuck_out_tongue_winking_eye:

f(x)= [f(x) for i in 1:x]; f(10)

EDIT:
Oh just “discovered” this one

d=[1.0]; while true append!(d,copy(d)) end