Syntax error when attempting to amend a string with indexing - indexing

I'm studying APL from here.
Why am I getting this syntax error?
'computer' [ 1 2 3 ] ← 'COM'
SYNTAX ERROR
'computer'[1 2 3]←'COM'
^
But if I save 'computer' in a variable I don't get the error:
T ← 'computer'
T
computer
T[1 2 3] ← 'COM'
T
COMputer
What am I doing wrong?

'computer' is a constant, and you can't change the value of a constant itself, only the current value of a variable.
Think about it: If you could assign to 'computer', then next time you wrote 'computer', would you expect the result to be COMputer? How about 2←3? Clearly, this doesn't make any sense.
However, you can amend a value without assigning it to a name, using the relatively new # "at" operator (it isn't included in Mastering Dyalog APL, but the documentation is available online).
'COM'#1 2 3⊢'computer'
COMputer
You can read this as put the letters 'COM' at indices 1 2 3 of the word 'computer'. The ⊢ here only serves to separate 1 2 3 from 'computer so it is clear to # what constitutes the indices and what is the array to be amended.
Run it on TryAPL!

That bracket notation is made specifically for modifying variables. The return value of T[1 2 3] ← 'COM' is 'COM', so if the expression didn't modify a variable, it would be pointless (or, almost identical to ⊢).
To get a modified array, not modify a variable, use the operator #:
('COM'#1 2 3) 'computer'
Try it online!

Related

Why do these 2 for looping over sequences differ?

First:
$ raku -e "for 1...6, 7...15 { .say }"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Now:
$ raku -e "for 1...3, 7...15 { .say }"
1
2
3
7
11
15
I would expect this case to print 1,2,3,7,8,... 15.
What's happening here?
I think you might want the raku Range operator .. (two dots) and not the raku Sequence operator ... (three dots).
Here's how you examples look with the Range operator instead:
> raku -e 'for 1..6, 7..15 { .say }'
1..6
7..15
Oh, that's not good ... looks like for is just iterating over the two things 1..6 and 7..15 and stringifying them.
We can use a Slip | to fix that:
> raku -e 'for |(1..6), |(7..15) { .say }'
1
2
... (all the numbers)
14
15
And then:
raku -e 'for |(1..3), |(7..15) { .say }'
1
2
3
7
8
9
10
11
12
13
14
15
With the Sequence operator, you have made something like:
>raku -e 'for 3,7...15 { .say }'
3
7
11
15
That is raku for "make a sequence that starts with 3, then 7, then all the values until you get to the last at 15" ... and since the gap from 3 to 7 is 4, raku will count up in steps of 4. Then you began it with 1..3. ;-)
~p6steve
It's because it is two deductive sequences.
1...3
Is obviously a sequence where you add 1 to each successive value.
1, 2, 3
And since 7 is 4 more than 3, this is a sequence where you add 4 to each successive value.
3, 7 ... 15
3, 7, 11, 15
To get what you want, you could use a flattened Range.
1...3, |(7..15)
Or even a flattened Sequence.
1...3, |(7...15)
TL;DR This answer focuses on addressing what you originally asked (which was about "sequences") and precisely what the code you wrote is doing, rather than providing a solution (using ranges instead).
This is a work in progress dealing with something that seems both poorly documented and hard to fathom (which may explain part though not all of the doc situation). Please bear with me! (And I may just end up deleting this answer.)
1 ... 3, 7 ... 15 ≡ 1 ... (3, 7) ... 15
In the absence of parentheses, operators within an expression are applied according to rules of "precedence" and "associativity".
Infix , has a higher precedence than infix ....¹ The above two lines of code thus produce the same result (1␤2␤3␤7␤11␤15␤):
for 1 ... 3, 7 ... 15 { .say } # Operator evaluation by precedence
for 1 ... (3, 7) ... 15 { .say } # Operator evaluation by parentheses
That said, while the result is what, given a glance at the code, I would expect based on my own "magical" DWIM ("Do What I Mean") thinking, I must say I don't yet know what the precise Raku(do)'s rule(s) are that lead to it DWIMing.
The doc for infix ... says:
If the endpoint is not *, it's smartmatched against each generated element and the sequence is terminated when the smartmatch succeeded.
But that seems overly simple. What if the endpoint of one sequence is another sequence? (As, at least taking a naive view, appears to be the case in your code.)
Also, as #MustafaAydin has noted:
how does your post explain the irregular last step size (of 2) instead of 3? I mean 4, 7 ... 15 alone produces (4, 7, 10, 13). But 1... 4, 7...15 now produces 7, 10, 13, 15 in the tail. Why is 15 included? Maybe i'm missing something idk
I'm at least as confused as Mustafa.
Indeed, I'm confused about several things. How come Raku(do) flattens the two sequences? [D'oh. Because the infix comma is higher precedence than the infix ....] Why doesn't it repeat the 3 in the final combined list? [Perhaps because multiple infix ...s are smart about what to do when there's an expression that's the endpoint of one sequence and the start of another?]
I'm going to go read the old design docs and/or spelunk roast and/or the Rakudo compiler code to see if I can see what's supposedly/actually going on. But not tonight.
Footnotes
¹ There's a table of operators in the current official operator doc. Supposedly this table:
summarizes the precedence levels offered by Raku, listing them in order from high to low precedence.
Unfortunately, at the time of writing this, the central operator table in the Operators page is profoundly wrong #4071.
Until that's fixed, here are "official" and "unofficial" options for determining the precedence of operators:
"official" Use in page search to search the official doc operator page for the operator of interest. Skip to the match in the entries on the left hand side of that same page. As you'll see, infix ,' is one level higher precedence than infix ...`:
Comma operator precedence
infix ,
infix :
List infix precedence
infix Z
infix X
infix ...
"unofficial" Look at the corresponding page of a staging site for an improved doc site. (I don't know how up to date it is, but the central table appears to list operators by precedence order as it claims.)

Generating variable observations for one id to be observation for new variable of another id

I have a data set that allows linking friends (i.e. observing peer groups) and thereby one can observe the characteristics of an individual's friends. What I have is an 8 digit identifier, id, each id's friend id's (up to 10 friends), and then many characteristic variables.
I want to take an individual and create a variables that are the foreign born status of each friend.
I already have an indicator for each person that is 1 if foreign born. Below is a small example, for just one friend. Notice, MF1 means male friend 1 and then MF1id is the id number for male friend 1. The respondents could list up to 5 male friends and 5 female friends.
So, I need Stata to look at MF1id and then match it down the id column, then look over to f_born for that matched id, and finally input the value of f_born there back up to the original id under MF1f_born.
edit: I did a poor job of explaining the data structure. I have a cross section so 1 observation per unique id. Row 1 is the first 8 digit id number with all the variables following over the row. The repeating id numbers are between the friend id's listed for each person (mf1id for example) and the id column. I hope that is a bit more clear.
Kevin Crow wrote vlookup that makes this sort of thing pretty easy:
use http://www.ats.ucla.edu/stat/stata/faq/dyads, clear
drop team y
rename (rater ratee) (id mf1_id)
bys id: gen f_born = mod(id,2)==1
net install vlookup
vlookup mf1_id, gen(mf1f_born) key(id) value(f_born)
So, Dimitriy's suggestion of vlookup is perfect except it will not work for me. After trying vlookup with both my data set, the UCLA data that Dimitriy used for his example, and a toy data set I created vlookup always failed at the point the program attempts to save a temp file to my temp folder. Below is the program for vlookup. Notice its sets tempfile file, manipulates the data, and then saves the file.
*! version 1.0.0 KHC 16oct2003
program define vlookup, sortpreserve
version 8.0
syntax varname, Generate(name) Key(varname) Value(varname)
qui {
tempvar g k
egen `k' = group(`key')
egen `g' = group(`key' `value')
local k = `k'[_N]
local g = `g'[_N]
if `k' != `g' {
di in red "`value' is unique within `key';"
di in red /*
*/ "there are multiple observations with different `value'" /*
*/ " within `key'."
exit 9
}
preserve
tempvar g _merge
tempfile file
sort `key'
by `key' : keep if _n == 1
keep `key' `value'
sort `key'
rename `key' `varlist'
rename `value' `generate'
save `file', replace
restore
sort `varlist'
joinby `varlist' using `file', unmatched(master) _merge(`_merge')
drop `_merge'
}
end
exit
For some reason, Stata gave me an error, "invalid file," at the save `file', replace point. I have a restricted data set with requirments to point all my Stata temp files to a very specific folder that has an erasure program sweeping it every so often. I don't know why this would create a problem but maybe it is, I really don't know. Regardless, I tweaked the vlookup program and it appears to do what I need now.
clear all
set more off
capture log close
input aid mf1aid fborn
1 2 1
2 1 1
3 5 0
4 2 0
5 1 0
6 4 0
7 6 1
8 2 .
9 1 0
10 8 1
end
program define justlinkit, sortpreserve
syntax varname, Generate(name) Key(varname) Value(name)
qui {
preserve
tempvar g _merge
sort `key'
by `key' : keep if _n ==1
keep `key' `value'
sort `key'
rename `key' `varlist'
rename `value' `generate'
save "Z:\Jonathan\created data sets\justlinkit program\fchara.dta",replace
restore
sort `varlist'
joinby `varlist' using "Z:\Jonathan\created data sets\justlinkit program\fchara.dta", unmatched(master) _merge(`_merge')
drop `_merge'
}
end
// set trace on
justlinkit mf1aid, gen(mf1_fborn) key(aid) value(fborn)
sort aid
list
Well, this fixed my problem. Thanks to all who responded I would not have figured this out without you.

Fortran runtime error while reading a file: "Bad repeat count"

I'm trying to read an input file with fortran but I get the following error at runtime:
At line 118 of file prog.f90 (unit = 53, file = 'data.dat')
Fortran runtime error: Bad repeat count in item 1 of list input
The data file is the following
3, 5, 3 %comment
%%%%%%%%%%%%%%
1d0, 0d0, 0d0 % comment
0d0, 0d0, 1d0
%%%%%%%%%%%%%%
1, 1, identity, 1, 1 %comment
1, 2, sigmax, 2, 2
2, 3, sigmax, 2, 2
1, 3, sigmaz, 1, 3
3, 3, identity, 1, 1
%%%%%%%%%%%%%%
0, 0 %comment
and the interesting part of prog.f90 is
COMPLEX(KIND(1D0)), DIMENSION(:), ALLOCATABLE:: H1, H2
INTEGER :: i,A,B,C
CHARACTER(50) :: GHOST
OPEN(UNIT=53,file='data.dat',status='old')
READ(53,*) A,B,C
READ(53,*) GHOST
ALLOCATE (H1(A),H2(A))
READ(53,*) (H1(i), i=1,A)
READ(53,*) (H2(i), i=1,A)
where the 118th line is READ(53,*) (H1(i), i=1,A). I tryed also with an explicit do loop but with the same result.
I haven't tested this, but I'd expect
READ(53,*) (H1(i), i=1,A)
to try to read 3 complex numbers. It gets fed the line
1d0, 0d0, 0d0 % comment
from which it gets 1½ complex numbers and then barfs on the % sign, misinterpreting it as a syntactically invalid repeat count.
I'd suggest providing 3 complex numbers in the file when that read statement is executed.
The numbers are dimensioned complex, while in fortran complex numbers should be in the file with parenthesis as:
( realpart , imaginarypart ) ( realpart , imaginarypart )
I really don't know what the standards say regarding the input form you have presented, but after some testing gfortran throws that Bad repeat count error regardless of the % comment. It throws that error even with four or more comma separated reals on the line.
Now ifort on the other hand reads the line just the way you have it -- but watch out -- it reads each of the comma separated values as the real part of your complex variable, setting the imaginary part to zero. ( that is it only uses the first two values on each line and discards the third )
You will really need to study the code to make sure you understand what was intended to sort out how to fix this. If the later (ifort) behavior is the intention one simple fix would be to declare a couple of reals. Read into the reals, then assign those to your complex variables.

Converting binary to decimal with out using a function

I'm trying to create a binary to decimal converter, and have got stuck on the code. I have researched forums for any help, but they all seam to use functions, which can not be used within a private sub. Please can anyone give me help on a solution to this problem?
I would use the positional notation method:
http://en.wikipedia.org/wiki/Positional_notation
http://www.wikihow.com/Convert-from-Binary-to-Decimal
So basically, without giving you the answer, you want to loop through binary place holders, filling up a variable as you go along. You would use an index to move from the least significant placeholder to the most.
For example : 10011011 in binary is 155 decimal.
So every place holder is a power with a base of two. Then you add the value for each one until your finished, like so:
placeholder 1 is: 2 pow 0 equals 1.
placeholder 2 is: 2 pow 1 equals 2.
placeholder 3 is: 2 pow 2 equals 4.
placeholder 4 is: 2 pow 3 equals 8.
placeholder 5 is: 2 pow 4 equals 16.
placeholder 6 is: 2 pow 5 equals 32.
placeholder 7 is: 2 pow 6 equals 64.
placeholder 8 is: 2 pow 7 equals 128.
Now we only add for the placeholders that have 1s.
128+16+8+2+1 = 155
What you will need:
A loop looping through indexes, and incrementing the exponent value as you go along, only adding the value if the index equals 1 in the binary number.
Hope my explanation makes sense. Good luck.

How to create words within a Forth definition

I'm using Gforth, and I want to create a word in a definition. In the cmd line of Gforth I can type:
create foo
ok
Or more specifically, I defined an array function that expects a size on the stack and creates a word with the address to that array:
: array ( n -- ) ( i -- addr)
create cells allot
does> cells + ;
So if I type 10 array foo I can then use foo later.
But if I were to write 10 array foo within another definition it gives me a compilation error. I've tried replacing foo with s" foo" which compiles, but it blows up at run time, saying:
Attempt to use zero-length string as a name
Is there a way to do this?
One way to do it in gforth:
: bar 10 s" foo" ['] array execute-parsing ;
Other implementations do it differently, e.g. http://pfe.sourceforge.net/words/w-header-015.html
It's not easy to do in Standard Forth, but this may be good enough:
: bar 10 s" array foo" evaluate ;
I guess most of what you want to do can be done by defining words, i.e. using create ... does> ... This allows you to define a word with specialized behaviour.
E.g.:
: 2const create , , does> 2# ;
can be used to create double constants like 2 3 2const a-double (that stashes 2 and 3 away in a-double) and then a-double pushes two values (2 3).