Suppose I have a struct Line
that takes two values. I want to write a function p(x)
that tkes [x_1,...,x_n]
and returns a vector of
[Line(x_1,x_2), Line(x_2,x_3)...]
.
I know I can simply write p(x) = map(Line, x[1:end-1], x[2:end])
, but I was looking for a functional programming way of doing this... Something in the lines of map((x,y)->Line(x,y) zip(head(x), tail(x))
... But this head
and tail
functions do not seem to be shipped on Julia. Also, it would be neat to have a general function for iterating over such pairs, triples, and so on.
I thought of using a foldl, but this does not work properly, as it returns something like Line(1,Line (2, Line(3,4))).
Another point is that the functiion should work for any Vector type, hence, it should not use stuff like [2:end], where one assumes that the vector has at least two values...
I imagine that p(x) should be something similar to a fold in the sense of having an init. For a singleton vector could perhaps return Line(init, x[1]), and for an empty vector it could return Line(init,init).
Any ideas?
It sounds like you just want to define a couple methods with that linear function to implement the iteration interface?
Base.iterate
and its 2 methods for your type, that is.
Davi Sales Barreira said:
Suppose I have a struct
Line
that takes two values. I want to write a functionp(x)
that tkes[x_1,...,x_n]
and returns a vector of
[Line(x_1,x_2), Line(x_2,x_3)...]
.I know I can simply write
p(x) = map(Line, x[1:end-1], x[2:end])
, but I was looking for a functional programming way of doing this...
What about that is not functional?
I took it to mean lazily compute the values, and then I immediately thought iteration interface. @Davi Sales Barreira if you check out the Interfaces section of the Manual, it lays out the iteration interface, and proceeds with an example similar (lazily computing the squares of a scalar) to what (I believe) you are looking for.
Doing this with iterators instead of slicing could work, but it sounds hard to do it in a way that wouldn't be silently incorrect with stateful iterators
Mason Protter said:
Davi Sales Barreira said:
Suppose I have a struct
Line
that takes two values. I want to write a functionp(x)
that tkes[x_1,...,x_n]
and returns a vector of
[Line(x_1,x_2), Line(x_2,x_3)...]
.I know I can simply write
p(x) = map(Line, x[1:end-1], x[2:end])
, but I was looking for a functional programming way of doing this...What about that is not functional?
I mean, it assumes the vector to be at least of size 2, hence it fails for the other cases.
I guess I don't understand what that has to do with functional programming
Neither do I
Here is what I came up with:
getlast(x::Nothing) = nothing
getlast(x::Tuple) = x[end]
safecollect(x::Nothing) = nothing
safecollect(x) = collect(x)
tail(x) = safecollect(getlast(Iterators.peel(x)))
head(x) = safecollect(getlast(Iterators.peel(Iterators.reverse(x))))
map(x->Line(x[1],x[2]), zip(head(x), tail(x)))
Mason Protter said:
I guess I don't understand what that has to do with functional programming
Sorry, I'm not very proficience on functional programming... When I say this, I mostly mean something that would be directly implementable in Haskell.
Makes sense?
Ok, so do you mean that you want state to be hidden away with monads?
Iterators may mutate the state, and it is explicitly passed as an argument.
I'm not sure how to program like haskell in Julia though, sorry.
Also, take a look at Base.front
and Base.tail
(not exported for some reason)
Is returning an empty list an acceptable fallback instead of some init
value?
julia> using Transducers
julia> struct Line{T}
x::T
y::T
end;
julia> [:x1, :x2, :x3] |> Consecutive(2; step=1) |> MapSplat(Line) |> collect
2-element Vector{Line{Symbol}}:
Line{Symbol}(:x1, :x2)
Line{Symbol}(:x2, :x3)
julia> [:x1,] |> Consecutive(2; step=1) |> MapSplat(Line) |> collect
Any[]
julia> [] |> Consecutive(2; step=1) |> MapSplat(Line) |> collect
Any[]
Very interesting. I've been trying to understand how transduscers work. I'll take a look at the package again. Thanks
If you feel a need for a haskell version of everything I guess you could look at https://github.com/hypirion/haskell-transducers
No idea if this thing is well implemented or not though
Personally, I think Transducers are a much more elegant and natural functional programming approach to data traversal than anything I've seen come out of Haskell land
Ok, I'm reading Transducers.jl documentation, and it's amazing. I was wondering if fthere is a formalization of it in terms of category theory,
@Davi Sales Barreira I am not sure, but also check out libraries that work with transducers, like Folds.jl and FLoops.jl
(also note that these projects live in the JuliaFolds organization, but the original maintainer went missing. Upgraded versions are forming in the JuliaFolds2 organization)
I was wondering if fthere is a formalization of it in terms of category theory
The core idea is not new, it's just the concept of lenses which are described in category theoretic terms here: https://ncatlab.org/nlab/show/lens+%28in+computer+science%29
but the details of various things are important, such as how transducers handle early termination, state, initialization, etc.
https://hypirion.com/musings/haskell-transducers
https://hypirion.com/musings/transducers-to-conduits-and-back
You mean @Takafumi Arakaki (tkf) is not contributing anymore??? I've followed lots of his sutff. Any idea on what happened?
Davi Sales Barreira said:
You mean Takafumi Arakaki (tkf) is not contributing anymore??? I've followed lots of his sutff. Any idea on what happened?
Since October, and unfortunately, nobody knows why.
Michael Fiano said:
Davi Sales Barreira said:
You mean Takafumi Arakaki (tkf) is not contributing anymore??? I've followed lots of his sutff. Any idea on what happened?
Since October, and unfortunately, nobody knows why.
That is truly unfortunate.
Davi Sales Barreira has marked this topic as resolved.
Last updated: Dec 28 2024 at 04:38 UTC