Does anybody know how to define a function with several statements in ML? - ml

I am trying to write a function in CPN ML which changes 3 variables, but I don't know how, I just can write one statement. My function should be something like this:
fun T1() =
x=x+1;
y=y+2;
k=k-1;
when I write this lines of code, I get an error.

Caveat: I don't know anything about CPN ML, but based on this I guess it has syntax similar to Standard ML?
In that case, you would need to group the statements in parentheses:
fun T1 () =
(x=x+1;
y=y+2;
k=k-1)

In SML, expressions can also be separated by semicolons in the body of a let expression, like this:
fun T1() =
let in
x=x+1;
y=y+2;
k=k-1
end
Some people prefer this to parentheses because it looks more block-structured. It also gives you a place to insert declarations (in the let .. in part), which is a common way for a function to evolve.
Of course, since this is a functional language, you either need to be using reference cells (x := !x + 1) or declaring new variables (val x = x + 1) to do what you have in the body of your function. There aren't really "statements" like in C and all variables are immutable.

Related

Optimizing custom fill of a 2d array in Julia

I'm a little new to Julia and am trying to use the fill! method to improve code performance on Julia. Currently, I read a 2d array from a file say read_array and perform row-operations on it to get a processed_array as follows:
function preprocess(matrix)
# Initialise
processed_array= Array{Float64,2}(undef, size(matrix));
#first row of processed_array is the difference of first two row of matrix
processed_array[1,:] = (matrix[2,:] .- matrix[1,:]) ;
#last row of processed_array is difference of last two rows of matrix
processed_array[end,:] = (matrix[end,:] .- matrix[end-1,:]);
#all other rows of processed_array is the mean-difference of other two rows
processed_array[2:end-1,:] = (matrix[3:end,:] .- matrix[1:end-2,:]) .*0.5 ;
return processed_array
end
However, when I try using the fill! method I get a MethodError.
processed_array = copy(matrix)
fill!(processed_array [1,:],d[2,:]-d[1,:])
MethodError: Cannot convert an object of type Matrix{Float64} to an object of type Float64
I'll be glad if someone can tell me what I'm missing and also suggest a method to optimize the code. Thanks in advance!
fill!(A, x) is used to fill the array A with a unique value x, so it's not what you want anyway.
What you could do for a little performance gain is to broadcast the assignments. That is, use .= instead of =. If you want, you can also use the #. macro to automatically add dots everywhere for you (for maybe cleaner/easier-to-read code):
function preprocess(matrix)
out = Array{Float64,2}(undef, size(matrix))
#views #. out[1,:] = matrix[2,:] - matrix[1,:]
#views #. out[end,:] = matrix[end,:] - matrix[end-1,:]
#views #. out[2:end-1,:] = 0.5 * (matrix[3:end,:] - matrix[1:end-2,:])
return out
end
For optimal performance, I think you probably want to write the loops explicitly and use multithreading with a package like LoopVectorization.jl for example.
PS: Note that in your code comments you wrote "cols" instead of "rows", and you wrote "mean" but take a difference. (Not sure it was intentional.)

R apply-like function for updating 2 arrays simultaneously?

I am new to R, and looking for an apply type function to work with 2 arrays at once (simultaneous update).
For example, let's say I have some variables X and P:
X = array(rep(0, 10), dim=c(10, 1))
P = array(rep(1, 10), dim=c(10, 1))
which are governed by the system of equations:
X[k,] = 2*X[k-1]
P[k,] = 3*X[k] + X[k-1] + 3
Obviously, this can easily be accomplished with a for-loop, however, I have read/confirmed myself that for loops work horrendously for large inputs, and I wanted to start getting into good R coding practice, so I am wondering, what is the best way to do this in an apply-type logic? I am looking for something like,
sapply(2:dim(X)[1], function(k) {
X[k,] = 2*X[k-1]
P[k,] = 3*X[k] + X[k-1] + 3
})
But this obviously won't work, as it doesn't actually update X and P internally. Any tips/tricks for how to make my for-loops faster, and get in better R coding practice? Thanks in advance!
You could do the following below. The <<- operator will set X and P outside of the function
sapply(2:dim(X)[1], function(k) {
X[k,] <<- 2*X[k-1]
P[k,] <<- 3*X[k] + X[k-1] + 3
})
As pointed out by thelatemail in the comments, using <<- can be problematic because of the side effects it can have. See the links below, the one comparing for loops (and other loops) to the apply family of functions.
Here is a link to documentation on assignment operators in R.
Here is a StackOverflow link on for loop vs. apply functions that talks about performance.

Can I have an "If" statement in a function parameter?

I'd like to use an IF statement in my VBA code where I'm calling up a Function and passing to it two parameters. The reason I need the IF statement is because the parameter is an array object that I pass to the function. Here's an abbreviation of the code that contains the problem:
For i = 1 To UBound(FilterArray)
For j = LBound(ptsheets, 1) To UBound(ptsheets, 1)
Filter_PivotField_Master _
pvtField:=ThisWorkbook.Worksheets(ptsheets(j, 1)).PivotTables(ptsheets(j, 2)).PivotFields(FilterArray(i, 1)), _
FilterTypeArray:= If FilterArray(i, 2) = 1 Then
InvCodeArray
Else
BoardMonthArray
End If
Next j
Next i
As you can see, I'm looping through the ptsheets array and for each entry, I'm calling up the Filter_PivotField_Master Function. The function requires two inputs (a pivotfield and a string array for the filtering). The array called "FilterArray" simply contains the info needed to pass along to the function. Because I can't seem to store the string array (either InvCodeArray or BoardMonthArray) within the "FilterArray," I wanted to use this IF statement to choose between either array based on if FilterArray(i,2) is equal to "1" or not. Is an "IF" statement option possible here?
Don't do that. Extract a method/procedure out of the inner loop, and parameterize it instead.
For j = LBound(ptsheets, 1) To UBound(ptsheets, 1)
Filter_PivotField_Master _
pvtField:=ThisWorkbook.Worksheets(ptsheets(j, 1)).PivotTables(ptsheets(j, 2)).PivotFields(thePivotField), _
FilterTypeArray:= theFilterType
Next j
Then have the calling code (the outer loop) implement the conditional logic that determines what parameters to give it.
Dim thePivotField
Dim theFilterType
For i = 1 To UBound(FilterArray)
thePivotField = FilterArray(i, 1)
If FilterArray(i, 2) = 1 Then
theFiltertype = InvCodeArray
Else
theFilterType = BoardMonthArray
End If
TheExtractedMethod i, thePivotField, theFilterType
Next i
Your code will be much easier to follow - and to debug.
On a related note, I made a few assumptions just to get your snippet to compile with Option Explicit on (and an IIf instead of the illegal If...Else block), and Rubberduck's last release (v1.4.3) correctly extracted the selected inner loop into its own method:
There are a few known bugs with Rubberduck 1.4.3, and v2.0 is coming soon-ish, but I thought this might interest you. I don't know any other refactoring tools for VBA. Note that Option Explicit is pretty much a hard requirement for this to work, since Rubberduck works off declarations and can't resolve undeclared variables.
Disclaimer: I wrote this refactoring tool.
Use an immediate IF (IIF) for this purpose.
FilterTypeArray = IIF(FilterArray(i, 2) = 1, InvCodeArray, BoardMonthArray)

SAS Do Over Macro - Backwards

I am using the Macro Arrays and Do Over Macro.
I would like to rewrite this code with a do over macro:
if mysequence > 4 then grammar_last_5 = grammar_last_4;
if mysequence > 3 then grammar_last_4 = grammar_last_3;
if mysequence > 2 then grammar_last_3 = grammar_last_2;
if mysequence > 1 then grammar_last_2 = grammar_last_1;
So my Do Over would look something like:
%do_over(values=2-5, phrase= if mysequence > %eval(6-?) then grammar_last_%eval(7-?) = grammar_last_%eval(6-?);)
But that doesn't work.
Does anyone know how this can be done?
Thanks!!
Adam
For others wondering, the macros appear to be available here: http://www.sascommunity.org/wiki/Tight_Looping_with_Macro_Arrays
You've got a problem though. You're trying to pass in %eval(6-?) and other functions like text to the %do_over macro. Its going to try to compute that function and pass the result to the macro, and because its finding a character in what should be a mathematical operation, I'm guessing it subsequently is throwing a bit of a tantrum.
What's more, a way to do what you want doesn't seem like it would be forthcoming, because you'd need to mask the function from the macro compiler as you're feeding it in as an argument, but then unmask it to the macro compiler as its actually being used by do_over, and I'm guessing do_over isn't going to understand what you want without rewriting its logic even if you succeeded.
May I humbly suggest your own macro code as a starting solution. Something like:
%do i = 5 %to 2 %by -1;
if mysequence > %eval(&i - 1) then grammar_last_&i = grammar_last_%eval(&i - 1);
%end;
This should produce the text you want, though you would need to put it in your own macro, and call it in a data step, as it wouldn't make much sense anywhere else.
If you're going to want something more generalized, you're going to have to get your hands much much messier...
I took a quick look at the macro and it looks like they use macro quoting functions which could be interfering with the execution of your %eval functions.
If this is the case then you would have to custom edit %do_over() so that it didn't do this. If so then it's probably not worth the effort. It would be easier to write your own one-off macro to achieve your goal.
You don't need a macro for that, unless you've got something you're not telling us.
if mysequence > 4 then grammar_last_5 = grammar_last_4;
if mysequence > 3 then grammar_last_4 = grammar_last_3;
if mysequence > 2 then grammar_last_3 = grammar_last_2;
if mysequence > 1 then grammar_last_2 = grammar_last_1;
->
array grammars grammar_last:;
do _t = 4 to 1 by -1; *or, _t = dim(grammars)-1 to 1 by -1;
if mysequence > _t then grammars[_t+1]=grammars[_t];
end;

How can I capture multiple return values in a call to MATLAB's arrayfun?

I have a function that takes an image as an argument and produces a label and a score as a result. I occasionally want to quickly test over a (cell) array of images, and the most convenient way I know to do this is using arrayfun. This works fine for getting the labels my function produces, but I would really like the output to be a list of [label score] cells.
I could write a wrapper around my function that captures both values and returns them as a cell matrix, and then call that wrapper within arrayfun, but it seems like this is a common enough idiom that there should be a way to work with multiple return values more conveniently. Is there? (Perhaps a standard convenience function already exists that can do this? Sort of like the opposite of deal...)
You can get your output as two matrices by using built-in syntax:
[A, B, ...] = arrayfun(fun, S, ...);
For example:
function [y,z]=foo(x)
y= x*x;
z = x + 10;
end
And then run the function :
[A,B] = arrayfun( #foo, magic(5))

Resources