Invalid Input Exception Handling - SmallTalk - smalltalk

Let a smalltalk msg named "sum" return the sum of elements in an array.
Eg: #(1 2 3 4 5) sum ----> 15
When the input is #(1 2 'a' 3 5) sum. The execution terminates and shows a big exception box.
Instead of that how can we gracefully exit the execution by just showing a message. I don't want the big exception window to be shown.
sum
|sum|
sum := 0
self do: [:a | sum := sum + a]
^sum
I tried to handle the exception the below way. However, I notice that the execution doesn't terminate in case of invalid input.
sum
|sum|
sum := 0
self do: [:a |
(a isInteger) ifFalse:[
^[Error signal] on: Exception
do: [:ex | Transcript show: 'Entered values are non-numeric. Hence comparison is not possible.']
]
sum := sum + a
]
^sum
If the below code is placed in the workspace, I expected the execution to be terminated at line 2. However, line 3 is also getting executed.
|temp|
temp := #(1 2 3 'as' 4 5) sum.
temp := temp*5.

Changing the sum method to ignore the wrong types in the input Array does not make sense. Furthermore by replacing it with a UI message you completely loose control over what kind of input is acceptable. Rather deal with these exception at the place you use sum:
[ ^ self readInput sum ]
on: Error do: [ :error| Transcript show: 'Invalid input provided for sum' ].

Related

What's the equivalent in Perl 6 to star expressions in Python?

In Python 3, suppose you run a course and decide at the end of the semester that you’re going to drop the first and last homework grades, and only average the rest of them:
def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)
print drop_first_last([100,68,67,66,23]);
In Perl 6:
sub drop_first_last(#grades) {
my ($first, *#middle, $last) = #grades;
return avg(#middle);
}
say drop_first_last(100,68,67,66,23);
Leads to the error "Cannot put required parameter $last after variadic parameters".
So, what's the equivalent express in Perl 6 as star expressions in Python?
sub drop_first_last(Seq() \seq, $n = 1) { seq.skip($n).head(*-$n) };
say drop_first_last( 1..10 ); # (2 3 4 5 6 7 8 9)
say drop_first_last( 1..10, 2 ); # (3 4 5 6 7 8)
The way it works: convert whatever the first argument is to a Seq, then skip $n elements, and then keep all except the last $n elements.
Perl5:
sub drop_first_last { avg( #_[ 1 .. $#_-1 ] ) } #this
sub drop_first_last { shift;pop;avg#_ } #or this
Perl6:
sub drop_first_last { avg( #_[ 1 .. #_.end-1 ] ) }
Use a slice.
sub drop_first_last (#grades) {
return avg(#grades[1..*-2])
}
Workarounds such as have been shown in the rest of the answer are correct, but the short answer to your question is that there is no equivalent expression in Perl 6 to the * in Python.
This kind of arguments are called, in general, variadic, and *slurpy+ in Perl 6, because they slurp the rest of the arguments. And that's the key, the rest. There can be no argument declared after an slurpy argument in a subroutine's signature. This example below also uses a workaround:
sub avg( #grades ) {
return ([+] #grades) / +#grades;
}
sub drop_first_last($first, *#other-grades) {
return avg(#other-grades[0..*-1]);
}
my #grades = <10 4 8 9 10 8>;
say drop_first_last( |#grades );
but is first using the slurpy * in the signature to show how it works, and then, by calling it with |#grades, is flattening the array instead of binding it into an array argument. So the long answer is that there is actually an * or variadic symbol in signatures in Perl 6, and it works similarly to how it would do it in Python, but it can only be placed last in those signatures since it captures the rest of the elements of the expression.
In case the first and last values are needed for some other reason,
unflattened list structure inside slices maps across to the results
in most cases, so you can do this (you have to use a $ sigil on
$middle to prevent autoflattening):
my #grades = (1,2,3,4,5,6);
my ($first, $middle, $last) = #grades[0,(0^..^*-1),*-1];
$first.say; $middle.say; $last.say;
#1
#(2 3 4 5)
#6

Rebol calc-workdays not working on Red

I trying to execute this script https://www.mail-archive.com/rebol-bounce#rebol.com/msg01222.html in Red but I can't see why I got
calc-workdays now/date 3-feb-2007 [1-feb-2007]
*** Script Error: > operator is missing an argument
*** Where: do
*** Stack: print calc-workdays
found?: func [
"Returns TRUE if value is not NONE."
value
][
not none? :value
]
calc-workdays: func [
"Return number of workdays between two dates, excluding holidays"
date1 [date!] "Start date"
date2 [date!] "End date"
holidays [block!] "Block of dates to exclude (holidays, etc.)"
/non "Return number of non-work days (weekend + holidays) between 2 dates"
/local days day1 day2 diff param
][
days: copy []
set [day1 day2] sort reduce [date1 date2]
diff: day2 - day1
param: pick [[> 5 union][< 6 exclude]] either found? non [1][2]
loop diff [
day1: day1 + 1
if do param/1 day1/weekday param/2 [append days day1]
]
return length? do param/3 days holidays
]
Rebol2 seems to allow you to pass a WORD! to DO, and evaluate it. If the word happens to be a variable holding an ANY-FUNCTION!, it will be run...and if it's an infix "OP!" then it will be run as if it were not infix.
>> do quote > 1 2
== false
>> do quote < 1 2
== true
Red sort of does this also, but DO is not variadic. It can run 0 arity functions only:
>> foo: does [print "hi"]
>> do quote foo
hi
>> bar: func [x] [print x]
>> do quote bar "hi"
*** Script Error: bar is missing its x argument
The script in question was attempting to use this feature. But it could be done with ordinary COMPOSE or REDUCE. So change:
if do param/1 day1/weekday param/2 [append days day1]
To:
if do reduce [day1/weekday param/1 param/2] [append days day1]
That will build a block of code where the > or < operator is in the middle, and execute it normally without relying on this WORD!-dispatch or infix-dropping behavior of DO.
Similarly, change:
return length? do param/3 days holidays
To:
return length? do reduce [param/3 days holidays]
With those changes, and removing the found? (it's not necessary) then it appears to work.

How to use a multiple line input to create my game?

So, i have one method that will create all of the instance variables for my other methods that will create the game, i know how to do them separately but finding how to do it from one method is really hard.
I need to be reading data from a String where each line must be treated separately.
Am using Pharo.
Class Game, everything is within one Game class.
Game: instance variables: 'rol col'. Using instance methods.
readFrom: 'Board 3 4
Dice 2 1 1 1
Players 1'
board
[my actual code that creates a board]
row for loop[
Transcript show: 'creating board'.
col for loop[
Transcript show: 'creating board'.
]
]
dice
[dice code..]
players
[players code]
Your model is not clearly defined yet. However, by helping you with some coding I will try to give you some insights on how to fill the gaps still remaining.
So, let's say you have a class Game. This class defines (at least) 4 instance variables: rows, columns, dice and players.
Now you want to create an instance of Game by reading some String that conforms to a certain format, such in:
'Board 3 4
Dice 2 1 1 1
Players 1'
To do this create a class side method in Game on the lines of
readFrom: aString
^self new readFrom: aString
and then an instance method
readFrom: aString
aString lines do: [:line | | data key |
data := line substrings.
key := data at: 1.
key = 'Board'
ifTrue: [
rows := data at: 2.
columns := data at: 3].
key = 'Dice'
ifTrue: [
dice := data allButFirst collect: [:s | s asInteger]].
key = 'Players'
ifTrue: [
players := (data at: 2) asInteger]]
Again, this won't solve all problems, but should help you get started. Otherwise, ask again.

SAS IML constraining a called function

How do I properly constrain this minimizing function?
Mincvf(cvf1) should minimize cvf1 with respect to h and I want to set so that h>=0.4
proc iml;
EDIT kirjasto.basfraaka var "open";
read all var "open" into cp;
p=cp[1:150];
conh={0.4 . .,. . .,. . .};
m=nrow(p);
m2=38;
pi=constant("pi");
e=constant("e");
start Kmod(x,h,pi,e);
k=1/(h#(2#pi)##(1/2))#e##(-x##2/(2#h##2));
return (k);
finish;
start mhatx2 (m2,newp,h,pi,e);
t5=j(m2,1); /*mhatx omit x=t*/
do x=1 to m2;
i=T(1:m2);
temp1=x-i;
ue=Kmod(temp1,h,pi,e)#newp[i];
le=Kmod(temp1,h,pi,e);
t5[x]=(sum(ue)-ue[x])/(sum(le)-le[x]);
end;
return (t5);
finish;
Start CVF1(h) global (newp,pi,e,m2);
cv3=j(m2,1);
cv3=1/m2#sum((newp-mhatx2(m2,newp,h,pi,e))##2);
return(cv3);
finish;
start mincvf(CVF1);
optn={0,0};
init=1;
call nlpqn(rc, res,"CVF1",init) blc="conh";
return (res);
finish;
start outer(p,m) global(newp);
wl=38; /*window length*/
m1=m-wl; /*last window begins at m-wl*/
newp=j(wl,1);
hyi=j(m1,1);
do x=1 to m1;
we=x+wl-1; /*window end*/
w=T(x:we); /*window*/
newp=p[w];
hyi[x]=mincvf(CVF1);
end;
return (hyi);
finish;
wl=38; /*window length*/
m1=m-wl; /*last window begins at m-wl*/
time=T(1:m1);
ttt=j(m1,1);
ttt=outer(p,m);
print time ttt p;
However I get lots of:
WARNING: Division by zero, result set to missing value.
count : number of occurrences is 2
operation : / at line 1622 column 22
operands : _TEM1003, _TEM1006
_TEM1003 1 row 1 col (numeric)
.
_TEM1006 1 row 1 col (numeric)
0
statement : ASSIGN at line 1622 column 1
traceback : module MHATX2 at line 1622 column 1
module CVF1 at line 1629 column 1
module MINCVF at line 1634 column 1
module OUTER at line 1651 column 1
Which happens because losing of precision when h approaches 0 and "le" in "mhatx2" approaches 0. At value h=0.4, le is ~0.08 so I just artificially picked that as a lower bound which is still precise enough.
Also this output of "outer" subroutine, ttt which is vector of h fitted for the rolling windows, still provides values below the constraint 0.4. Why?
I have solved loss of precision issues previously by simply applying a multiplication transformation to the input... Multiply it by 10,000 or whatever is necessary, and then revert the transformation at the end.
Not sure if it will work in your situation, but it may be worth a shot.
This way it works, had to put that option and constrain vector both into the input parentheses:
Now I get no division by 0 warning. The previously miss-specified-due-loss-of-precision point's are now not specified at all and the value is substituted by 0.14 but the error isn't likely big.
start mincvf(CVF1);
con={0.14 . .,. . .,. . .};
optn={0,0};
init=1;
call nlpqn(rc, res,"CVF1",init,optn,con);
return (res);
finish;

Recursion: why the top of the stack is repeating twice

I don't understand why the top of the stack is repeating two times.
Here's my code:
void count(n){
if (n>0) {
printf("Count is %i \n",n);
n=n-1;
count(n);
} else {
printf("Count is %i. Finished. \n",n);
}
printf("The count here is %i \n",n); //recursion here
}
int main(int argc, const char * argv[])
{
#autoreleasepool {
count(5);
}
return 0;
}
The output is:
Count is 5
Count is 4
Count is 3
Count is 2
Count is 1
Count is 0. Finished.
The count here is 0
The count here is 0
The count here is 1
The count here is 2
The count here is 3
The count here is 4
Program ended with exit code: 0
So, why are there two lines of output that say "The count here is 0" ?
Isn't the first line, the 'first' time through the recursion?
Think about your code logically and I think you will see why that line is being printed twice. Consider the case when we reach this statement: n=n-1; and n is currently (before this is executed) equal to 1. Now n is 0 and you call count(n), calling your function recursively as I think you might have been saying. Now your count(0) function call will go here:
else {
printf("Count is %i. Finished. \n",n);
}
because n is not greater than 0. This is where we have your output: Count is 0. Finished.
Then, your functions next statement is: printf("The count here is %i \n",n); //recursion here
This causes the first output of: The count here is 0.
Now consider what happens. Your count(0) call is done and returns to the function it was called from. In this case, consider where you called it from. You called it from the function which was called as count(1), but now in that function, be causes of your n=n-1;, n is 0.
Following your code, after the if statement, your program will immediately proceed to: printf("The count here is %i \n",n); //recursion here
Because n is 0, it will output: The count here is 0 again.
Are you sure you want:
n=n-1;
count(n);
rather than this?
count(n-1);
The former will modify the value of n printed in your later printf, whereas the latter only modifies it in the recursive call.