async Elixir vs async Julia - asynchronous

In Elixir I can run code asynchronously like this
defmodule Async do
def example do
process_id = Task.async(fn ->
#some code you want its result later
end)
#do some stuff
async_result = Task.await(process_id)
end
end
and, if i don't need any results I can do like this
defmodule Async do
def example do
process_id = Task.start_link(fn ->
#some code you want its result later
end)
#do some stuff
:ok
end
end
What's the equivalent of above in Julia lang?

if you do not care about the result, you can use #async:
function foo()
sleep(100)
sum(1:100)
end
julia> #async foo()
Task (runnable) #0x00007f983b9d5f90
julia>
in the above example you get back the control of the terminal, without having to wait until the end of the execution of foo()
if you want to know the result, and keep an asynchronous behavior, you can use Task, schedule and fetch together:
julia> a() = sum(1:10000)
a (generic function with 1 method)
julia> b = Task(a)
Task (runnable) #0x00007f983b9d5cf0
julia> schedule(b)
Task (done) #0x00007f983b9d5cf0
julia> fetch(b)
50005000
Here is a small piece of code I use to illustrate the different behaviors:
module async
function example1()
a() = #async sleep(2)
b = Task(a)
schedule(b)
println(fetch(b))
sleep(4)
fetch(b)
end
function example2()
a() = sleep(2)
b = Task(a)
schedule(b)
fetch(b)
end
function example3()
a() = sum(1:10000)
b = Task(a)
schedule(b)
fetch(b)
end
end;
when I run this code, I get:
julia> async.example1()
Task (runnable) #0x00007f983b9d5510
Task (done) #0x00007f983b9d5510
julia> async.example2()
julia> async.example3()
50005000
async.example2() does not return any result, but keep the terminal busy around 2 seconds since fetch waits for the task to complete before giving back the hand.

Related

Changing the input (i.e. x+2y) of a macro to an expression ( :(x+2y)), How to produce the same output?

The code at the end of this post constructs a function which is bound to the variables of a given dictionary. Furthermore, the function is not bound to the actual name of the dictionary (as I use the Ref() statement).
An example:
julia> D = Dict(:x => 4, :y => 5)
julia> f= #mymacro4(x+2y, D)
julia> f()
14
julia> DD = D
julia> D = nothing
julia> f()
14
julia> DD[:x] = 12
julia> f()
22
Now I want to be able to construct exactly the same function when I only have access to the expression expr = :(x+2y).
How do I do this? I tried several things, but was not able to find a solution.
julia> f = #mymacro4(:(x+2y), D)
julia> f() ### the function evaluation should also yield 14. But it yields:
:(DR.x[:x] + 2 * DR.x[:y])
(I actually want to use it within another macro in which the dictionary is automatically created. I want to store this dictionary and the function within a struct, such that I'm able to call this function at a later point in time and manipulate the objects in the dictionary. If necessary, I may post the complete example and explain the complete problem.)
_freevars2(literal) = literal
function _freevars2(s::Symbol)
try
if typeof(eval(s)) <: Function
return s
else
return Meta.parse("DR.x[:$s]")
end
catch
return Meta.parse("DR.x[:$s]")
end
end
function _freevars2(expr::Expr)
for (it, s) in enumerate(expr.args)
expr.args[it] = _freevars2(s)
end
return expr
end
macro mymacro4(expr, D)
expr2 = _freevars2(expr)
quote
let DR = Ref($(esc(D)))
function mysym()
$expr2
end
end
end
end

Break Function without return

I have a function
function foo(a)
if a > 5
a = 5
end
some_more_code
end
If the if-statement is true I would like to end the function but I don't want to return anything - to change the value of a is all I need.
How do I do that?
You can write (note that I have also changed the syntax of function definition to make it more standard for Julia style):
function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
Just use the return keyword without any expression following it. To be precise in such cases Julia returns nothing value of type Nothing from a function (which is not printed in REPL and serves to signal that you did not want to return anything from a function).
Note though that the value of a will be only changed locally (within the scope of the function), so that outside of the function it will be unchanged:
julia> function foo(a)
if a > 5
a = 5
return
end
# some_more_code
end
foo (generic function with 1 method)
julia> x = 10
julia> foo(x)
julia> x
10
In order to make the change visible outside of the function you have to make a to be some kind of container. A typical container for such cases is Ref:
julia> function foo2(a)
if a[] > 5
a[] = 5
return
end
# some_more_code
end
foo2 (generic function with 1 method)
julia> x = Ref(10)
Base.RefValue{Int64}(10)
julia> foo2(x)
julia> x[]
5

How to pass a function typesafe in julia

Let's say, I want to pass a function to another function:
function foo()
return 0;
end
function bar(func)
return func();
end
print(bar(foo));
But you can make functions typesafe:
function func(t::Int)
print(t);
end
func(0); #produces no error
func("Hello world"); #produces an error
I didn't found out, how I combine both, that means, how can I explicitly define a parameter of bar, like func, to be a function, possibly with certain input / output argument types.
Thanks in advance for any help.
If I understand you correctly you want to make sure the passed function returns a specific type? The simplest thing is to just typeassert the return value at runtime:
julia> function f(func)
val = func()::Int # Error if the return value is not of type Int
return val
end
f (generic function with 1 method)
julia> f(() -> 1)
1
julia> f(() -> 1.0)
ERROR: TypeError: in typeassert, expected Int64, got Float64
Stacktrace:
[1] f(::var"#7#8") at ./REPL[5]:2
[2] top-level scope at REPL[8]:1
Alternatively you can use the FunctionWrappers.jl package (which will convert to the specified return type, or error if the conversion is not possible):
julia> using FunctionWrappers: FunctionWrapper
julia> function f(func::FunctionWrapper{Int,<:Tuple})
val = func()
return val
end;
julia> function f(func)
fw = FunctionWrapper{Int,Tuple{}}(func)
return f(fw)
end;
julia> f(() -> 1)
1
julia> f(() -> 1.0) # Can convert to Int
1
julia> f(() -> 1.2) # Can not convert to Int
ERROR: InexactError: Int64(1.2)
A function is of type Function. You can easily check this:
julia> foo() = 1;
julia> T = typeof(foo)
typeof(foo)
julia> supertype(T)
Function
julia> foo isa Function
true
This will not necessarily cover all callable types, as you can make any type callable:
julia> struct Callable end
julia> (::Callable)(x::Number) = x + one(x)
julia> callable = Callable()
Callable()
julia> callable(5)
6
julia> callable isa Function
false

In Julia 1.0+: How do I get strings using redirect_stdout

The documentation for redirect_stdouton version 1.1.0, that I am currently using, does not seem to give an example of how to use that function. Maybe I missed it?
I want to capture the output of println and get it back as a string.
Here is an example:
julia> VERSION
v"1.1.0"
julia> (rd, wr) = redirect_stdout();
julia> println("This is a test.")
julia> # Get back the string "This is a test."
julia> # s = do_something_with_rd(rd)
julia> # s == "This is a test."
julia> # true
Any suggestions?
Edit
Based on the accepted answer below, here is a complete solution to my question:
julia> original_stdout = stdout;
julia> (rd, wr) = redirect_stdout();
julia> println("This is a test.")
julia> s = readline(rd)
"This is a test."
julia> s == "This is a test."
true
julia> redirect_stdout(original_stdout);
julia> println("Test of orig. stdout.")
Test of orig. stdout.
Edit 2: A More Complete Example
Here is an example of testing a variety of print and println function outputs using redirection of stdout. Thanks to #Bogumił Kamiński for his answer and edit that made this more clear to me:
using Test
# Test redirect_stdout.
#testset "Example tests using redirect_stdout" begin
original_stdout = stdout;
(read_pipe, write_pipe) = redirect_stdout();
print("Using print function.")
println("Using println function.")
println("Second use of println function.")
println("Line 1.\nLine 2.\nLine 3.\nEND")
println("""
This is new line 1.
This is new line 2. Next a Char = """)
print('A')
redirect_stdout(original_stdout);
close(write_pipe)
#test readline(read_pipe) == "Using print function.Using println function."
#test readline(read_pipe) == "Second use of println function."
#test read(read_pipe, String) == "Line 1.\nLine 2.\nLine 3.\nEND\n" *
"This is new line 1.\nThis is new line 2. Next a Char = \nA"
end
# Suppress unnecessary output when this file.
return nothing
Here is the output:
julia> include("test_redirect_stdout.jl")
Test Summary: | Pass Total
Example tests using redirect_stdout | 3 3
Just run readline on rd (or any other reading operation).
You have just to be careful that read operations on rd are blocking, i.e. the terminal will seem to hang when the operation cannot be completed. One solution is to use #async for this. For instance:
julia> (rd, wr) = redirect_stdout();
julia> #async global x = readline(rd) # if we did not put #async here the terminal would be blocked
Task (runnable) #0x0000000004e46e10
julia> x # x is yet undefined as readline is waiting for an input
ERROR: UndefVarError: x not defined
julia> println("something") # we feed data to stdout
julia> x # and readline has finished its work and bound the value to variable x
"something"
Of course if you know exactly that the data you want to read in is there just run readline or some other function and all will work without #async.
EDIT
Given the comments from SalchiPapa I think it is also add this pattern of possible usage as it is simplest to think of IMO:
original_stdout = stdout
(rd, wr) = redirect_stdout();
println("This is a test 1.")
println("This is a test 2.")
println("This is a test 3.")
redirect_stdout(original_stdout)
# you can still write to wr
println(wr, "This is a test 4.")
# you have to close it to make the read non-blocking
close(wr)
# the pipe is redirected to original stdout and wr is closed so this is non-blocking
s = read(rd, String)
You could use sprint AKA "string print":
https://docs.julialang.org/en/v1/base/io-network/index.html#Base.sprint
julia> sprint(println, "This is a test")
"This is a test\n"

Generating type-stable `getfield` calls using generated functions

I would like to be able to create a dispatch for a user-defined type which will essentially do an inplace copy. However, I would like to do it in a type-stable manner, and thus I would like to avoid using getfield directly, and instead try to use a generated function. Is it possible for a type like
type UserType{T}
x::Vector{T}
y::Vector{T}
z::T
end
to generate some function
recursivecopy!(A::UserType,B::UserType)
# Do it for x
if typeof(A.x) <: AbstractArray
recursivecopy!(A.x,B.x)
else
A.x = B.x
end
# Now for y
if typeof(A.y) <: AbstractArray
recursivecopy!(A.y,B.y)
else
A.y = B.y
end
# Now for z
if typeof(A.z) <: AbstractArray
recursivecopy!(A.z,B.z)
else
A.z = B.z
end
end
The recursivecopy! in RecursiveArrayTools.jl makes this handle nested (Vector{Vector}) types well, but the only problem is that I do not know the fields the user will have in advance, just at compile-time when this function would be called. Sounds like a job for generated functions, but I'm not quite sure how to generate this.
You don't need to bend over backwards to avoid getfield and setfield. Julia can infer them just fine. The trouble comes when Julia can't figure out which field it's accessing… like in a for loop.
So the only special thing the generated function needs to do is effectively unroll the loop with constant values spliced into getfield:
julia> immutable A
x::Int
y::Float64
end
julia> #generated function f(x)
args = [:(getfield(x, $i)) for i=1:nfields(x)]
:(tuple($(args...)))
end
f (generic function with 1 method)
julia> f(A(1,2.4))
(1,2.4)
julia> #code_warntype f(A(1,2.4))
Variables:
#self#::#f
x::A
Body:
begin # line 2:
return (Main.tuple)((Main.getfield)(x::A,1)::Int64,(Main.getfield)(x::A,2)::Float64)::Tuple{Int64,Float64}
end::Tuple{Int64,Float64}
Just like you can splice in multiple arguments to a function call, you can also directly splice in multiple expressions to the function body.
julia> type B
x::Int
y::Float64
end
julia> #generated function f!{T}(dest::T, src::T)
assignments = [:(setfield!(dest, $i, getfield(src, $i))) for i=1:nfields(T)]
:($(assignments...); dest)
end
f! (generic function with 1 method)
julia> f!(B(0,0), B(1, 2.4))
B(1,2.4)
julia> #code_warntype f!(B(0,0), B(1, 2.4))
Variables:
#self#::#f!
dest::B
src::B
Body:
begin # line 2:
(Main.setfield!)(dest::B,1,(Main.getfield)(src::B,1)::Int64)::Int64
(Main.setfield!)(dest::B,2,(Main.getfield)(src::B,2)::Float64)::Float64
return dest::B
end::B
You can, of course, make the body of that comprehension as complicated as you'd like. That effectively becomes the inside of your for loop. Splatting the array into the body of the function does the unrolling for you.

Resources