defined-or "//" over multiple lines - raku

Why are version 1,2 and 3 working, but version 4 fails with: Null regex not allowed when using // over multiple lines?
#1
say Nil //
try {'a'++} //
1;
#2
say Nil
// try {'a'++} //
2;
#3
say Nil
// 3;
#Fails with: Null regex not allowed
say Nil
// try {'a'++}
// 4;

There is try block at the end of a line.
It is same as
say Nil
// try {'a'++};
// 4;
See documentation:
It is OK to skip the semicolon between the last statement in a block and the closing }.
You can try
say Nil
// try {'a'++}\
// 4;
or
say Nil
// (try {'a'++})
// 4;

Related

Unable to understand the certain operator in Swift

I have been changing some SWIFT code into OBJECTIVE-C, and I am stuck at certain part of the code, where I am unable to understand if it is a condition or something else.
Following is the code and I am stuck on 9th line stating :
if let channel1Buffer = buffer.floatChannelData?[0]
What I do not understand here is the above if condition is checking if "buffer.floatChannelData" is null, and then proceeding to get the first index, or is it something else.
input.installTap(onBus: 0, bufferSize:4096, format:format, block: { [weak self] buffer, when in
guard let this = self else {
return
}
print("Buffer Float Channel Data: ", buffer.floatChannelData as Any);
**if let channel1Buffer = buffer.floatChannelData?[0]** {
print("channel1Buffer: ", channel1Buffer);
/// encode PCM to mp3
let frameLength = Int32(buffer.frameLength) / 2;
print("frameLength: ", frameLength);
let bytesWritten = lame_encode_buffer_interleaved_ieee_float(this.lame, channel1Buffer, frameLength, this.mp3buf, 4096);
// `bytesWritten` bytes stored in this.mp3buf now mp3-encoded
print("\(bytesWritten) encoded");
this.file.append(this.mp3buf, length: Int(bytesWritten));
// #TODO: send data, better to pass into separate queue for processing
}
})
Let's take it part by part - buffer.floatChannelData?[0]
buffer has property named floatChannelData which is optional so it has ? at the end. then it takes that optional which accepts subscription [0] which also returns optional value. So it continues inside {} only if floatChannelData is not nil AND it's first value is not nil
Your Objc should look like
float *const *channelData = [buffer floatChannelData];
if (channelData) {
float *channel1Buffer = channelData[0]; //this might crash if channelData is empty
...
The line tries to assign the variable channel1Buffer the value of buffer.floatChannelData[0], and the code within {} is only executed if that assignment is successful. It may for instance fail if buffer.floatChannelData is nil or buffer.floatChannelData[0] is nil.

How do I create a variable in go only if a condition is true?

If I create a variable inside an if block, I can't use it later on. If I create a variable before the if block and the if block evaluates to false, I get a "variable created and not used" error.
I'm certain that this is by design and I'm trying to do something I shouldn't, but the logic behind what I'm trying to do makes sense to me. If there is page info in the url, I want to use it in a sql statement later on, but if there isn't page info in the url, then I don't need those variables.
http://pastebin.com/QqwpdM1d
Edit: here's the code:
var pageID string
var offset int
if len(r.URL.Path) > len("/page/") {
pageID := r.URL.Path[len("/page/"):]
offset, err := strconv.Atoi(pageID)
if err != nil {
log.Fatal(err)
}
}
conn := "..."
db, err := sql.Open("mysql", conn)
defer db.Close()
if err != nil {
log.Fatal(err)
}
var rows *sql.Rows
if offset != 0 {
// ...
}
If you declare a variable before an if statement and you use it inside the if block, it doesn't matter what the condition evaluates to, it is not a compile time error.
The error in you case is that you don't use the declared variable inside the if block. Your code:
var pageID string
var offset int
if len(r.URL.Path) > len("/page/") {
pageID := r.URL.Path[len("/page/"):]
offset, err := strconv.Atoi(pageID)
if err != nil {
log.Fatal(err)
}
}
Inside the if you are not assigning to the previously declared pageID, but you are using short variable declaration := which creates a new variable, shadowing the one created in the outer block, and it is in effect only at the end of the if block (its scope ends at the end of the innermost containing block).
Solution is (what you most likely wanted to) simply use assignment = (which assigns value to the existing variable):
pageID = r.URL.Path[len("/page/"):]
To make it understand, see this example:
i := 1
fmt.Println("Outer:", i)
{
i := 2 // Short var decl: creates a new i, shadowing the outer
fmt.Println("Inner:", i)
}
fmt.Println("Outer again:", i)
Output (try it on the Go Playground):
Outer: 1
Inner: 2
Outer again: 1

sending characters from parent to child process and returning char count to parent in C

So for an assignment I have for my Computer Systems class, I need to type characters in the command line when the program runs.
These characters (such as abcd ef) would be stored in argv[].
The parent sends these characters one at a time through a pipe to the child process which then counts the characters and ignores spaces. After all the characters are sent, the child then returns the number of characters that it counted for the parent to report.
When I try to run the program as it is right now, it tells me the value of readIn is 4, the child processed 0 characters and charCounter is 2.
I feel like I'm so close but I'm missing something important :/ The char array for a and in the parent process was an attempt to hardcode the stuff in to see if it worked but I am still unsuccessful. Any help would be greatly appreciated, thank you!
// Characters from command line arguments are sent to child process
// from parent process one at a time through pipe.
//
// Child process counts number of characters sent through pipe.
//
// Child process returns number of characters counted to parent process.
//
// Parent process prints number of characters counted by child process.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> // for fork()
#include <sys/types.h> // for pid_t
#include <sys/wait.h> // for waitpid()
int main(int argc, char **argv)
{
int fd[2];
pid_t pid;
int status;
int charCounter = 0;
int nChar = 0;
char readbuffer[80];
char readIn = 'a';
//char a[] = {'a', 'b', 'c', 'd'};
pipe(fd);
pid = fork();
if (pid < 0) {
printf("fork error %d\n", pid);
return -1;
}
else if (pid == 0) {
// code that runs in the child process
close(fd[1]);
while(readIn != 0)
{
readIn = read(fd[0], readbuffer, sizeof(readbuffer));
printf("The value of readIn is %d\n", readIn);
if(readIn != ' ')
{
charCounter++;
}
}
close(fd[0]);
//open(fd[1]);
//write(fd[1], charCounter, sizeof(charCounter));
printf("The value of charCounter is %d\n", charCounter);
return charCounter;
}
else
{
// code that runs in the parent process
close(fd[0]);
write(fd[1], &argv, sizeof(argv));
//write(fd[1], &a, sizeof(a));
close(fd[1]);
//open(fd[0]);
//nChar = read(fd[0], readbuffer, sizeof(readbuffer));
nChar = charCounter;
printf("CS201 - Assignment 3 - Andy Grill\n");
printf("The child processed %d characters\n\n", nChar);
if (waitpid(pid, &status, 0) > 0)
{
if (WIFEXITED(status))
{
}
else if (WIFSIGNALED(status))
{
}
}
return 0;
}
}
You're misusing pipes.
A pipe is a unidirectional communication channel. Either you use it to send data from a parent process to a child process, or to send data from a child process to the parent. You can't do both - even if you kept the pipe's read and write channels open on both processes, each process would never know when it was its turn to read from the pipe (e.g. you could end up reading something in the child that was supposed to be read by the parent).
The code to send the characters from parent to child seems mostly correct (more details below), but you need to redesign child to parent communication. Now, you have two options to send the results from child to parent:
Use another pipe. You set up an additional pipe before forking for child-to-parent communication. This complicates the design and the code, because now you have 4 file descriptors to manage from 2 different pipes, and you need to be careful where you close each file descriptor to make sure processes don't hang. It is also probably a bit overkill because the child is only sending a number to the parent.
Return the result from the child as the exit value. This is what you're doing right now, and it's a good choice. However, you fail to retrieve that information in the parent: the child's termination status tells you the number of characters processed, you can fetch this value with waitpid(2), which you already do, but then you never look at status (which contains the results you're looking for).
Remember that a child process has its own address space. It makes no sense to try to read charCounter in the parent because the parent never modified it. The child process gets its own copy of charCounter, so any modifications are seen by the child only. Your code seems to assume otherwise.
To make this more obvious, I would suggest moving the declarations of variables to the corresponding process code. Only fd and pid need to be copied in both processes, the other variables are specific to the task of each process. So you can move the declarations of status and nChar to the parent process specific code, and you can move charCounter, readbuffer and readIn to the child. This will make it very obvious that the variables are completely independent on each process.
Now, some more specific remarks:
pipe(2) can return an error. You ignore the return value, and you shouldn't. At the very least, you should print an error message and terminate if pipe(2) failed for some reason. I also noticed you report errors in fork(2) with printf("fork error %d\n", pid);. This is not the correct way to do it: fork(2) and other syscalls (and library calls) always return -1 on error and set the errno global variable to indicate the cause. So that printf() will always print fork error -1 no matter what the error cause was. It's not helpful. Also, it prints the error message to stdout, and for a number of reasons, error messages should be printed to stderr instead. So I suggest using perror(3) instead, or manually print the error to stderr with fprintf(3). perror(3) has the added benefit of appending the error message description to the text you feed it, so it's usually a good choice.
Example:
if (pipe(fd) < 0) {
perror("pipe(2) error");
exit(EXIT_FAILURE);
}
Other functions that you use throughout the code may also fail, and again, you are ignoring the (possible) error returns. close(2) can fail, as well as read(2). Handle the errors, they are there for a reason.
The way you use readIn is wrong. readIn is the result of read(2), which returns the number of characters read (and it should be an int). The code uses readIn as if it were the next character read. The characters read are stored in readbuffer, and readIn will tell you how many characters are on that buffer. So you use readIn to loop through the buffer contents and count the characters. Something like this:
readIn = read(fd[0], readbuffer, sizeof(readbuffer));
while (readIn > 0) {
int i;
for (i = 0; i < readIn; i++) {
if (readbuffer[i] != ' ') {
charCounter++;
}
}
readIn = read(fd[0], readbuffer, sizeof(readbuffer));
}
Now, about the parent process:
You are not writing the characters into the pipe. This is meaningless:
write(fd[1], &argv, sizeof(argv));
&argv is of type char ***, and sizeof(argv) is the same as sizeof(char **), because argv is a char **. Array dimensions are not kept when passed into a function.
You need to manually loop through argv and write each entry into the pipe, like so:
int i;
for (i = 1; i < argv; i++) {
size_t to_write = strlen(argv[i]);
ssize_t written = write(fd[1], argv[i], to_write);
if (written != to_write) {
if (written < 0)
perror("write(2) error");
else
fprintf(stderr, "Short write detected on argv[%d]: %zd/zd\n", i, written, to_write);
}
}
Note that argv[0] is the name of the program, that's why i starts at 1. If you want to count argv[0] too, just change it to start at 0.
Finally, as I said before, you need to use the termination status fetched by waitpid(2) to get the actual count returned by the child. So you can only print the result after waitpid(2) returned and after making sure the child terminated gracefully. Also, to fetch the actual exit code you need to use the WEXITSTATUS macro (which is only safe to use if WIFEXITED returns true).
So here's the full program with all of these issues addressed:
// Characters from command line arguments are sent to child process
// from parent process one at a time through pipe.
//
// Child process counts number of characters sent through pipe.
//
// Child process returns number of characters counted to parent process.
//
// Parent process prints number of characters counted by child process.
#include <stdlib.h>
#include <stdio.h>
#include <string.h> // for strlen()
#include <unistd.h> // for fork()
#include <sys/types.h> // for pid_t
#include <sys/wait.h> // for waitpid()
int main(int argc, char **argv)
{
int fd[2];
pid_t pid;
if (pipe(fd) < 0) {
perror("pipe(2) error");
exit(EXIT_FAILURE);
}
pid = fork();
if (pid < 0) {
perror("fork(2) error");
exit(EXIT_FAILURE);
}
if (pid == 0) {
int readIn;
int charCounter = 0;
char readbuffer[80];
if (close(fd[1]) < 0) {
perror("close(2) failed on pipe's write channel");
/* We use abort() here so that the child terminates with SIGABRT
* and the parent knows that the exit code is not meaningful
*/
abort();
}
readIn = read(fd[0], readbuffer, sizeof(readbuffer));
while (readIn > 0) {
int i;
for (i = 0; i < readIn; i++) {
if (readbuffer[i] != ' ') {
charCounter++;
}
}
readIn = read(fd[0], readbuffer, sizeof(readbuffer));
}
if (readIn < 0) {
perror("read(2) error");
}
printf("The value of charCounter is %d\n", charCounter);
return charCounter;
} else {
int status;
if (close(fd[0]) < 0) {
perror("close(2) failed on pipe's read channel");
exit(EXIT_FAILURE);
}
int i;
for (i = 1; i < argc; i++) {
size_t to_write = strlen(argv[i]);
ssize_t written = write(fd[1], argv[i], to_write);
if (written != to_write) {
if (written < 0) {
perror("write(2) error");
} else {
fprintf(stderr, "Short write detected on argv[%d]: %zd/%zd\n", i, written, to_write);
}
}
}
if (close(fd[1]) < 0) {
perror("close(2) failed on pipe's write channel on parent");
exit(EXIT_FAILURE);
}
if (waitpid(pid, &status, 0) < 0) {
perror("waitpid(2) error");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("CS201 - Assignment 3 - Andy Grill\n");
printf("The child processed %d characters\n\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "Child terminated abnormally with signal %d\n", WTERMSIG(status));
} else {
fprintf(stderr, "Unknown child termination status\n");
}
return 0;
}
}
Some final notes:
The shell splits arguments by spaces, so if you start the program as ./a.out this is a test, the code will not see a single space. This is irrelevant, because spaces are supposed to be ignored anyway, but if you want to test that the code really ignores spaces, you need to quote the parameters so that the shell does not process them, as in ./a.out "this is a test" "hello world" "lalala".
Only the rightmost (least significant) 8 bits of a program's exit code are used, so WEXITSTATUS will never return more than 255. If the child reads more than 255 characters, the value will wrap around, so you effectively have a character counter modulo 256. If this is a problem, then you need to go with the other approach and set up a 2nd pipe for child-to-parent communication and write the result there (and have the parent read it). You can confirm this on man 2 waitpid:
WEXITSTATUS(status)
returns the exit status of the child. This consists of the least
significant 8 bits of the status argument that the child
specified in a call to exit(3) or _exit(2) or as the argument for a return
statement in main(). This macro should be employed only if
WIFEXITED returned true.

EXC_BAD_ACCESS when reading 9 characters, but works with less than 9

I'm developing a console app in Objective-C. I've got it working, but when manually testing edge cases, I found a strange behavior that I can't explain.
Basically, I've set up scanf() in a loop, and when the user types invalid info, it prints an "invalid option" message. Then, if the input is less than 9 characters long, it goes through the loop again as intended. But, if the input is 9 characters or longer, it gives a EXC_BAD_ACCESS error on a certain line.(This error doesn't happen if I comment out said line.)I can't figure out any reason why 8 vs 9 characters being read would cause this error. Any ideas?
Below are the two methods that I figure are relevant, with a comment on the line throwing the error. If you think other referenced code may be causing this, let me know and I'll add that code.
-(void)startMenu {
printf("\nGAME OPTIONS\n| WinningScore = %d (w) | Name = %s (n) | Back (b) |\n",
_options.winningScore, [_options.name UTF8String]);
}
-(void)start {
char selectedOption;
char w = 'w';
char n = 'n';
char b = 'b';
while(YES) {
[self startMenu]; // This line gets the EXC_BAD_ACCESS error
// if the user puts in 9 or more characters.
// If it is commented out, then no error is thrown.
scanf("%s", &selectedOption);
if(selectedOption == w) {
[self setWinningScore];
} else if(selectedOption == n) {
[self setName];
} else if(selectedOption == b) {
break;
} else {
printf("'%s' is not a valid option.\n", &selectedOption);
}
}
}
It this was C (and the post is tagged C) I'd suggest:
char selectedOption;
....
scanf(" %c", &selectedOption);
...
printf("'%c' is not a valid option.\n", selectedOption);
The failure showing up after a 9 charterer input is serendipity. scanf("%s", &selectedOption); is certainly wrong for reading a single character. Any input starts causing problems. Use the matching format specifier and variable.
[Edit]
A C-like solution.
If more than 1 char is desire for input, use the idea put forth by #Devolus. Example:
char selectedOption[10];
if (fgets(selectedOption, sizeof selectedOption, stdin) == NULL)
Handle_EOForIOerror();
// Get rid of potential trailing \n if desired.
size_t len = strlen(selectedOption);
if (len > 0 && selectedOption[len-1] == '\n') selectedOption[--len] = '\0';
You should use fgets instead of scanf here, as you can limit the number of characters in the buffer.
scanf is potentially unsafe because the buffer can be exceeded.

Can an If Statement tell if an assignment was valid?

I have an object that returns a value if successful and false (or nil) if it failed.
i want to assign that value to a variable
if(var1 = [object foo])
{
//if the [object foo] returned a variable, goes here
}
else
{
//[object foo] returned FALSE (or nil), go here
}
can an If statement detected if an assignment was valid?
This is all right but will generate a warning, since this is a common typo (= instead of ==). To silence that warning add another set of parentheses like this:
if ((var = [object foo])) ...
Since this easily can lead to misunderstandings a lot of people will advise against doing this. For a simple if statement this is much clearer to do the assignment first:
var = [object for];
if (var) ...
In while loops this is more useful, but also considered harmful by many people.
Not sure I understand your question, but let me try and explain a few situations you can check
1) Property contains value
if ([object foo])
{
// If foo has a value associated to it that is not nil/false/zero
}
else
{
// If foo equals nil, false or zero
}
2) Assignment to a variable was successful
if ((bar = [object myMethod]))
{
// If myMethod returns any non-nil value
}
else
{
// If myMethod returns nil
}
3) Previous assignment of a variable was successful
bar = [object myMethod];
if (bar)
{
// If bar has a value associated to it that is not nil/false/zero
}
else
{
// If bar equals nil, false or zero
}
use == instead of = in the if statement.
before the if statement, you may have var1 = [object foo]
see comparison operators
If you mean by valid that the variable contains an expected result, you can just perform another if on the variable against the expected result, or null to check it.