I wanted to try a mental experiment of creating a stateful function by using only pure ones, without using any sorts of assignment/monads and such. For instance, a function resembling a RS-flipflop, which has Set and Reset inputs:
ff(1,0) -> 1 ; SET
ff(0,0) -> 1 ; just output current state
ff(0,1) -> 0 ; RESET
ff(0,0) -> 0 ; whoops, a side-effect!
In electronics such a flipflop (or any stateful circuit) is implemented by sending output of a circuit back to the input, i.e:
So, I am thinking that some sort of recursion of functions can create stateful functions, right? But how to handle the thing, that it will be infinite?
Related
I'm quite new to Erlang (Reading through "Software for a Concurrent World"). From what I've read, we link two processes together to form a reliable system.
But if we need more than two process, I think we should connect them in a ring. Although this is slightly tangential to my actual question, please let me know if this is incorrect.
Given a list of PIDs:
[1,2,3,4,5]
I want to form these in a ring of {My_Pid, Linked_Pid} tuples:
[{1,2},{2,3},{3,4},{4,5},{5,1}]
I have trouble creating an elegant solution that adds the final {5,1} tuple.
Here is my attempt:
% linkedPairs takes [1,2,3] and returns [{1,2},{2,3}]
linkedPairs([]) -> [];
linkedPairs([_]) -> [];
linkedPairs([X1,X2|Xs]) -> [{X1, X2} | linkedPairs([X2|Xs])].
% joinLinks takes [{1,2},{2,3}] and returns [{1,2},{2,3},{3,1}]
joinLinks([{A, _}|_]=P) ->
{X, Y} = lists:last(P)
P ++ [{Y, A}].
% makeRing takes [1,2,3] and returns [{1,2},{2,3},{3,1}]
makeRing(PIDs) -> joinLinks(linkedPairs(PIDs)).
I cringe when looking at my joinLinks function - list:last is slow (I think), and it doesn't look very "functional".
Is there a better, more idiomatic solution to this?
If other functional programmers (non-Erlang) stumble upon this, please post your solution - the concepts are the same.
Use lists:zip with the original list and its 'rotated' version:
1> L=[1,2,3].
[1,2,3]
2> lists:zip(L, tl(L) ++ [hd(L)]).
[{1,2},{2,3},{3,1}]
If you are manipulating long lists, you can avoid the creation of the intermediary list tl(L) ++ [hd(L)] using an helper function:
1> L = lists:seq(1,5).
[1,2,3,4,5]
2> Link = fun Link([Last],First,Acc) -> lists:reverse([{Last,First}|Acc]);
Link([X|T],First,Acc) -> Link(T,First,[{X,hd(T)}|Acc]) end.
#Fun<erl_eval.42.127694169>
3> Joinlinks = fun(List) -> Link(List,hd(List),[]) end.
#Fun<erl_eval.6.127694169>
4> Joinlinks(L).
[{1,2},{2,3},{3,4},{4,5},{5,1}]
5>
But if we need more than two process, I think we should connect them
in a ring.
No. For instance, suppose you want to download the text of 10 different web pages. Instead of sending a request, then waiting for the server to respond, then sending the next request, etc., you can spawn a separate process for each request. Each spawned process only needs the pid of the main process, and the main process collects the results as they come in. When a spawned process gets a reply from a server, the spawned process sends a message to the main process with the results, then terminates. The spawned processes have no reason to send messages to each other. No ring.
I would guess that it is unlikely that you will ever create a ring of processes in your erlang career.
I have trouble creating an elegant solution that adds the final {5,1} tuple.
You can create the four other processes passing them self(), which will be different for each spawned process. Then, you can create a separate branch of your create_ring() function that terminates the recursion and returns the pid of the last created process to the main process:
init(N) ->
LastPid = create_ring(....),
create_ring(0, PrevPid) -> PrevPid;
create_ring(N, PrevPid) when N > 0 ->
Pid = spawn(?MODULE, loop, [PrevPid]),
create_ring(.......).
Then, the main process can call (not spawn) the same function that is being spawned by the other processes, passing the function the last pid that was returned by the create_ring() function:
init(N) ->
LastPid = create_ring(...),
loop(LastPid).
As a result, the main process will enter into the same message loop as the other processes, and the main process will have the last pid stored in the loop parameter variable to send messages to.
In erlang, you will often find that while you are defining a function, you won't be able to do everything that you want in that function, so you need to call another function to do whatever it is that is giving you trouble, and if in the second function you find you can't do everything you need to do, then you need to call another function, etc. Applied to the ring problem above, I found that init() couldn't do everything I wanted in one function, so I defined the create_ring() function to handle part of the problem.
I am processing input data that comes in "alternating" lines.
In order to handle that nicely, I (and SO) came up with this code:
val foobars = mutableListOf<FooBar>()
lines.chunked(2) { (l1, l2) ->
foobars.add( FooBar( generateFoo(l1), generateBar(l2) )
}
The above works, but it seems a bit odd to first create that empty list, and to then append to it in order to "collect" the freshly created objects.
If this would be a Java stream, the "collecting" part would be straight forward, using a List collector.
Now I am wondering if there is more elegant/canonical way of collecting my list items in kotlin?
It's actually simpler then you think, e.g.
val foobars = lines.chunked(2) { (l1, l2) ->
FooBar( generateFoo(l1), generateBar(l2) )
}.toMutableList()
The difference to a Java stream is, that you can actually operate on a list (/sequence/iterable) directly and you get a new one in return every time you call something like chunked, filter, map, toList, toMutableList, etc. So after calling chunked (+ transformation) you got a new list containing the transformations. You then can transform it to a (new) mutable list just by calling toMutableList().
And if you do not need to alter the list later, you can just skip toMutableList() and you have your list already.
Following is a sample code that uses case statement and always #(*) block. I don't get how the always block is triggered and why it works even when x is declared as wire.
wire [2:0] x = 0;
always #(*)
begin
case (1'b1)
x[0]: $display("Bit 0 : %0d",x[0]);
x[1]: $display("Bit 1 : %0d",x[1]);
x[2]: $display("Bit 2 : %0d",x[2]);
default: $display("In default case");
endcase
end
Any help is appreciated.
Thanks.
As we know, reg can be driven by a wire, we can definitely use a wire as the right hand side of the assignment in any procedural block.
Here, your code checks which bit of x is 1'b1 (of course giving priority to zeroth bit). Lets say x changes to 3'b010. Then, Bit 1 shall be displayed and so on. Now, if x=3'b011 then Bit 0 is displayed since zeroth bit is checked first.
As you can see, there is no assignment to x, the procedural block only reads its value. Moreover, the system task $display also reads the value of x.
There is no change of signal value from this block. Hence, this code works fine. If, by chance, we had something like x[0] = ~x[0] instead of $display, then this code shall provide compilation issues.
More information can be found at this and this links.
Here, this always block does not assign a value to a x, but it just checks a value of x. So it's a legal use of wire.
So, the explanation to the part of your question about how always #(*) is triggered is as follows :
"Nets and variables that appear on the right-hand side of assignments, in subroutine calls, in case and conditional expressions, as an index variable on the left-hand side of assignments, or as variables in case item expressions shall all be included in always #(*)."
Ref: IEEE Std 1800-2012 Sec 9.4.2.2
As an extension of #sharvil111's answer, if your code was something like this
always #(*)
begin
case (sel)
x[0]: $display("Bit 0 : %0d",x[0]);
x[1]: $display("Bit 1 : %0d",x[1]);
x[2]: $display("Bit 2 : %0d",x[2]);
default: $display("In default case");
endcase
end
The procedural block would be triggered whenever there is a change in sel signal or x i.e. it would be equivalent to always #(sel or x).
I define an outer syntax command, imake to write some code to a file and do some other things. The intended usage is as follows:
theory Scratch
imports Complex_Main "~/Is0/IsS"
begin
imake ‹myfile›
end
The above example will write some contents to the file myfile. myfile should be a path relative to the location of the Scratch theory.
ML ‹val this_path = File.platform_path(Resources.master_directory #{theory})
I would like to be able to use the value this_path in specifying myfile. The imake command is defined in the import ~/Is0/IsS and currently looks as follows:
ML‹(*imake*)
val _ = Outer_Syntax.improper_command #{command_spec "imake"} ""
(Parse.text >>
(fn path => Toplevel.keep
(fn _ => Gc.imake path)))›
The argument is pased using Parse.text, but I need feed it the path based on the ML value this_path, which is defined later (in the Scratch theory). I searched around a lot, trying to figure out how to use something like Parse.const, but I won't be able to figure anything out any time soon.
So: It's important that I use, in some way, Resources.master_directory #{theory} in Scratch.thy, so that imake gets the folder Scratch is in, which will come from the use of #{theory} in Scratch.
If I'm belaboring the last point, it's because in the past, I wasted a lot of time getting the wrong folder, because I didn't understand how to use the command above correctly.
How can I achieve this?
Your minimal examples uses Resource.master_directory with the parameter #{theory} to define your path. #{theory} refers (statically) to the theory at the point where you write down the antiquotation. This is mostly for interactive use, when you explore stuff. For code which is used in other places, you must use the dynamically passed context and extract the theory from it.
The function Toplevel.keep you use takes a function Toplevel.state -> unit as an argument. The Toplevel.state contains a context (see chapter 1 of the Isabelle Implementation Manual), which again contains the current theory; with Toplevel.theory_of you can extract the theory from the state. For example, you could use
Toplevel.keep (fn state => writeln
(File.platform_path (Resources.master_directory (Toplevel.theory_of state))))
to define a command that prints the master_directory for your current theory.
Except in simple cases, it is very likely that you do not only need the theory, but the whole context (which you can get with Toplevel.context_of).
Use setup from preceding (parts of the) theory
In the previous section, I assumed that you always want to use the master directory. For the case where the path should be configurable, Isabelle knows the concept of configuration options.
In your case, you would need to define an configuration option before you declare your imake command
ML ‹
val imake_path = Attrib.setup_config_string #{binding imake_path}
(K path)
› (* declares an option imake_path with the value `path` as default value *)
Then, the imake command can refer to this attribute to retrieve the path via Config.get:
Toplevel.keep (fn state =>
let val path = Config.get (Toplevel.context_of state) imake_path
in ... end)
The value of imake_path can then be set in Isar (only as a string):
declare [[imake_path="/tmp"]]
or in ML, via Config.map (for updating proof contexts) or Config.map_global (for updating theories). Note that you need to feed the updated context back to the system. Isar has the command setup (takes an ML expression of type theory -> theory) for that:
setup ‹Config.map_global imake_path (K "/tmp")›
Configuration options are described in detail in the Isar Implementation Manual, section 1.1.5.
Note: This mechanism does not allow you to automatically set imake_path to the master directory for each new theory. You need to set it manually, e.g. by adding
setup ‹
Config.map imake_path
(K (File.platform_path (Resources.master_directory #{theory})))
›
at the beginning of each theory.
The more general mechanism behind configuration options is context data. For details, see section 1.1 and in particular section 1.1.4 of the Isabelle Implementation Manual). This mechanism is used in a lot of places in Isabelle; the simpset, the configuration of the simplifier, is one example for this.
I'm very new to SNL/NJ and was wondering how I could accomplish the following:
foo(stuff,counter)
{
while(counter > 0)
{
bar(stuff);
counter-1;
}
return;
}
Something like this, but how do I decrement?:
foo(stuff,counter) =
while counter > 0 do bar(stuff) ??? // how do I decrement counter here?
I agree with the other contributors that you should generally use recursion instead of loops and mutation to do this in a functional language.
If you really wanted to use mutation and loops though, you would need to use a data structure called a reference which is a kind of "mutable cell". You allocate the reference with the ref function, passing it the initial contents. You access the contents using the ! operator. And you set new contents using the := operator. So the literal translation of your code above would be something like the following. As you can see, the syntax is really ugly and that is another reason why people avoid it.
fun foo (stuff, counter_start) =
let
val counter = ref counter_start
in
while !counter > 0 do (
bar stuff;
counter := !counter - 1
)
end;
In a functional program, a mutable variable turns into a parameter, typically to a nested helper function.
Since in your example, the thing being mutated is aleady parameter, no helper function is needed. Your code becomes
fun foo stuff counter =
if counter > 0 then
( bar stuff
; foo stuff (counter-1)
)
else
()
Of course this code is still terribly imperative... The call bar stuff is executed purely for side effect. Not very ML-ish.
Short answer: You don't. In functional programming, you generally never modify variables, which means a loop is impossible. Instead, you can implement the same using recursion. Similarly, since you don't, generally speaking, have side effects, function calls only make sense if they return data. So bar(stuff) is probably not very useful. It has no way of affecting the rest of the application. In a functional programming style, your bar() function should be called on different data each time, and return something that the rest of the application can act on.
(ML does allow side effects in certain cases, but to keep things simple, let's ignore that for now)
What exactly are you trying to achieve? (What do you need to loop over, what do the functions do?
If you provide a bit more detail, we can explain more specifically how you should write the program. But as it is, your program simply doesn't make sense in a functional style.
I don't know ML, but this is some ML-like pseudo code:
fun foo stuff 0 = return ()
| foo stuff counter = (bar stuff; foo stuff (counter - 1))
I don't know how to "chain" commands in ML; the semicolon is just a placeholder.
Generally, you wouldn't loop. I would rather expect the usual higher order functions. When you get used to those, manually writing a loop will feel like coding assembler.
edit: fixed code according to comment