I'm writing a little scripting language just for a bit of fun and the learning of the codes :P
I would just like your opinions/suggestions. I have an idea but I don't want to include something that people are going to want to spit on. I plan on making this language open source once, soon.
Does anybody think that it would be cool to have something like:
[Foreach] Uppercase Letter s
in Case-Insensitive Word SallySawtheSeafiShandateit:
Count++.
s.Highlight: True.
RunOnce.ProtectedMethod.ActivateProtectedMethod: IsTrue.
[Protected Method.LockTo: [Foreach]].IsTrue
StatusBar.Message: Match for s was found. Total: Count..
RunOnce.ProtectedMethod.Disable.
Explanation: What the above actually does is it searches through a string of text "SallySawtheSeafiShandateit" and highlights every single match. But when it finds the very first match for "s", it runs a method called "IsTrue", and sets the statusbar text to "match was found...". And then deactivates the RunOnce method so it may no longer be accessed, since there's no need for it to be run again.
This might not be the best example, but I think you get the idea. There have been plenty of times where I've needed to do something only once in a foreach loop, but couldn't, without writing a whole bunch of other code.
I figure, atleast this way, everything can be done in just two methods.
Please be brutally honest. :)
Thank you
This just seems like an over-complication of the following structure (in java style):
boolean ranOnce = false;
for (char c : string.toCharArray()) {
if (c != 's') continue;
if (!ranOnce) {
// do stuff once
ranOnce = true;
}
// do other stuff
}
It just seems like extreme over-engineering to me, when a single boolean and an if condition do the trick.
Hm. For this sort of situation I'd normally just use a flag variable and a conditional.
I'd reconsider "runOnce" -- it's a little ambiguous. Does it run the first iteration, the last iteration, somewhere in the middle? From what I can tell it looks like yours runs in the very first iteration, but then again what use would displaying the total count be in the first iteration? You'll know it's just "1".
For my money, I think I'd actually use two keywords that fired events/methods/etc at the first iteration and at the last iteration, respectively.
Related
I write a wrong expression sum(A14+A15:A19). Actually the right way for me is A14+sum(A15:A19). Curiously, the former can run as well with no error. So I spent much time to check the adequate result and find the odd phenomenon.
Besides, when I input the expression in the row 20,21 , error appears. Is that a bug? What's the meaning?
Thanks.
The sum function takes in parameters separated by ,s (not +s).
It's a little counterintuitive, since you're trying to add things together, but instead of =sum(A14+A15:A19) try = sum(A14,A15:A19).
All that being said, I assume there's a reason why you wouldn't simplify the whole thing and use =sum(A14:A19).
I am using the actionscript-mode by Austin Haas with Emacs 23.3.1. When I write a function in ActionScript with a lot of arguments, I like to split it into several lines. I would like it to look like
public function foo(bar:Bar,
baz:Baz,
qux:Qux):void {...}
But with the indentation of the actionscript-mode, it looks like
public function foo(bar:Bar,
baz:Baz,
qux:Qux):void {...}
This annoys me a lot. Is there any way to fix this?
A short answer is: I don't see there's a good way to do it at all. Today indentation is based only on the previous line, and it is completely broken if E4X is used, or nested object literals or array literals and so on :(
Below is however, something that might help you out if you don't mind some handwork applied to each such instance you want to modify:
(defun as3-align-regex ()
(interactive)
(let ((align-to-tab-stop nil))
(align-regexp (region-beginning) (region-end)
"\\(\\s(\\|\\s-\\)\\(\\sw+\\)" 1 1 nil)))
Note that you need to select the region in a way that it starts with the first parenthesis, bracket or space and until the last term that you want to align. It's kind of ugly, but a good solution would require too much effort.
"If it works, don't touch it"...I understand. That said, the code I'm extending is studded with blocks like this:
EVALUATE TRUE ALSO TRUE
WHEN FOO-YES ALSO BAR-YES
PERFORM ACTION
WHEN OTHER
SET ERROR TO TRUE
END-EVALUATE
To my inexperienced eye, IF seems clearer:
IF FOO-YES AND BAR-YES
PERFORM ACTION
ELSE
SET ERROR TO TRUE
ENDIF
When writing new functionality, is there a reason to prefer EVALUATE over IF?
There is no reason to prefer EVALUATE over IF. I do, but I don't have a good reason for it. I try to code so it is easy for the maintainer to understand, but there are going to be cases where the logic is complex and you end up with constructs like...
EVALUATE TRUE ALSO TRUE ALSO TRUE
WHEN INITIAL-STATE ALSO ANY ALSO ANY
PERFORM 0100-INITIALIZE
PERFORM 1000-DISPLAY-MENU
WHEN MENU-DISPLAYED ALSO DFHRESP(NORMAL) ALSO UPDATE-REQUESTED
PERFORM 2000-DO-THE-UPDATE
EXEC CICS RETURN END-EXEC
[...and so forth...]
END-EVALUATE
Somewhere there's a quote about how things should be as simple as possible, but no simpler. There are, of course, many ways to code the same logic. Different people find different constructs easier to understand. Lots of arguments occur because of those differences.
You read it correctly. "True ALSO True" is a very odd thing to code.
Often you will see an "Evaluate True", in which case the when conditions all act EXACTLY like IF statements. Using ALSO introduces some possible oddities, as it isn't just like the CASE statements from all the other languages.
A nicer way to write this is:
Evaluate true
when FOO-YES and BAR-YES
perform action
when other
set error to true
End-Evaluate
Granted, TRUE ALSO TRUE is very easy to understand, but you could have TRUE ALSO WS-BLAH-BLAH and it could get confusing. The Cobol Evaluate verb is very powerful, and sometimes easy to shoot yourself in the foot with. That said, it is very powerful and will let you do alot.
It is often the case that convoluted IF's that don't nest cleanly can be fixed up nicely with a well written Evaluate.
I may say that makes the life easy in certain situations. Say for instance where we'll get to add another condition based on which we may need to PERFORM different chunk of code; in that case appending another WHEN would be easy rather than adjusting the conditions on IF. Here are the points when compared WHEN against adjusting conditions on IF:
We would have a feasibility to provide as many WHEN(s) as we want based on the PARAs to be performed.
IF conditions are prone to mistakes while working with OR or AND parameters
Also WHEN gives clear picture of how things flow where as we may have to adjust our glasses while analyzing IF(s). [This may happen when we have complicated loops, but as an efficient programmer we ought to forecast such scenarios]
Last but not the least, retrofitting back the code to previous state would be easy with less number of IFs.
But in your current case, i dont feel much clarity and as well difference between EVALUATE and IF. So, go for the one which makes you happy :)
To me it all comes down to readability (and hence, simpler maintenance later on).
When I look at the 2 code segments in your question, I find the IF block far more readable.
In 22 years of Cobol programming I have never used an ALSO in an EVALUATE.
And using an EVALUATE block for a simple binary true/false test seems a bit obtuse to me.
But don't get me wrong, I love EVALUATEs when used appropriately. When I started programming in Java 6 years ago, EVALUATE was the thing I missed most. Sure, Java has switch, but that can't be used as flexibly as EVALUATE.
Consider the following code segment:
IF ACTION = "START"
PERFORM START
ELSE IF ACTION = "STOP"
PERFORM STOP
ELSE IF ACTION = "PROCESS" AND FILE-NAME = "A"
PERFORM PROCESS-A-FILE
ELSE IF ACTION = "PROCESS" AND FILE-NAME = "B"
PERFORM PROCESS-B-FILE
ELSE IF ACTION = "RESET"
PERFORM RESET
ELSE
PERFORM INVALID-ACTION-ERROR.
This collection of IF statements has some real problems. Without adding 5 END-IFs to the end of it, you have to end the block with a full-stop. But you wouldn't be able to do that if the code was inside a PERFORM UNTIL ... END-PERFORM block, say. While this example is fairly simple, in a more complicated (and longer) example, it could get tricky to figure out which ELSE goes with which IF.
This is crying out to be put in an EVALUATE TRUE block, thus:
EVALUATE TRUE
WHEN ACTION = "START"
PERFORM START
WHEN ACTION = "STOP"
PERFORM STOP
WHEN ACTION = "PROCESS" AND FILE-NAME = "A"
PERFORM PROCESS-A-FILE
WHEN ACTION = "PROCESS" AND FILE-NAME = "B"
PERFORM PROCESS-B-FILE
WHEN ACTION = "RESET"
PERFORM RESET
WHEN OTHER
PERFORM INVALID-ACTION-ERROR
END-EVALUATE
Changing this EVALUATE to have TRUE ALSO TRUE would make it far less readable, and it really isn't necessary.
I have the following code snippet in one of my COBOL program.
IF FIRST < SECOND
MOVE FIRST TO WS
END-IF.
MOVE SECOND TO WS.
MOVE WS TO RESULT.
I need to use GO TO inside the IF block to jump to the last statement (MOVE WS TO RESULT).
IF FIRST < SECOND
MOVE FIRST TO WS
GO TO <last line.(MOVE WS to RESULT)>
END-IF.
MOVE SECOND TO WS.
MOVE WS TO RESULT.
in other word, i need to skip "MOVE SECOND TO WS.".
what is the simplest way to jump to a specific line in cobol?
I read somewhere that this is possible by defining a PARAGRAPH, but don't know how to define it.
It might seems very simple but I'm newbie to COBOL programming.
Thanks.
----------------* UPDATE *----------
based on #lawerence solution, is this correct?
IF FIRST < SECOND
MOVE FIRST TO WS
GO TO C10-END.
END-IF.
MOVE SECOND TO WS.
C10-END.
MOVE WS TO RESULT.
i just moved back the last statement to be in first level.
GOTO can do what you're looking for, but IF/ELSE would be more direct. You want MOVE SECOND TO WS to run iff the IF block does not, correct?
IF FIRST < SECOND
MOVE FIRST TO WS
ELSE
MOVE SECOND TO WS
END-IF.
MOVE WS TO RESULT.
I hope I got the syntax right, I have never used COBOL and just tried to work off your snippet and this example http://www.fluffycat.com/COBOL/If-and-End-If/. There probably will be situations in the future where you need GOTO, but it A) should be avoided when another control structure will work and B) I haven't the slightest idea how its done
to be honest, COBOL looks pretty miserable lol. ive never seen a language so verbose. good luck with everytihng
EDIT
Mostly for joe...
Cant this all be better done with a min function? I'm sure the syntax is wrong, but:
Move Function Min(FIRST, SECOND) to RESULT
OMFSM! It is not 1974, why are you writing Cobol like that? This:
IF FIRST < SECOND
MOVE FIRST TO WS
END-IF.
MOVE SECOND TO WS.
MOVE WS TO RESULT.
Has a number of problems:
It uses periods to delimit scope, that is nearly three decades deprecated.
It isn't using ELSE
It is trying to use GO TO.
May I suggest the following as the way to approach it since 1985:
If FIRST < SECOND
Move FIRST to WS
Else
Move SECOND to WS
End-IF
Move WS to RESULT
But really, the code should simply read:
If FIRST < SECOND
Move FIRST to RESULT
Else
Move SECOND to RESULT
End-If
Unless the intermediate result is needed in WS. Cobol 66 and 74 used GOTO and periods because they lacked modern control structures. I realize you are a 'newbie', but you should suggest to whoever is teaching you that they really need to upgrade their skills.
jon_darkstar is right when it comes to improving the logic, however if you want to see how GO TO works here goes:
IF FIRST < SECOND
MOVE FIRST TO WS
GO TO C10-RESULT.
END-IF.
MOVE SECOND TO WS.
C10-RESULT.
MOVE WS TO RESULT.
C10-RESULT. starts a paragraph and has to be a unique name in your code SECTION. By convention it should also start with the same prefix as the enclosing section. Therefore this example assumes that your code SECTION is something like C00-MAIN-PROCESS SECTION.
A new non-Answer has brought this silly question to light.
ELSE in the IF is the 100% obvious answer. It is deeply odd that GO TO has to be used whereas ELSE may not be used.
Another way, surprised it didn't come up:
MOVE SECOND TO WS
IF FIRST LESS THAN SECOND
MOVE FIRST TO WS
END-IF
MOVE WS TO RESULT
No ELSE, no GO TO. Extra MOVE executed when FIRST is less than second, though.
To include a GO TO is simple, but stupid. Add a GO TO. A GO TO has to go somewhere (unless using ALTER ... TO PROCEED TO ..., which everyone hopes you weren't), so make a label at the point you want it to arrive, and add the name of that label to the GO TO.
A label is a user-defined word. If referenced (as in this case) it must be unique within a SECTION, if you use SECTIONs, which you don't need to, otherwise unique within the program and whether referenced or not it may not be the same name as something else (like a data-definition or the internal name of a file).
A label is a procedure-name. A procedure-name should terminate with a period/full-stop and the procedure itself should also terminate with a period/full-stop.
What about the MOVE FUNCTION MIN ( ... ) ... as a solution?
Well, it works. If other staff at your site are not used to it, you will not be thanked for using it (without prior discussion, anyway).
What does it do? Well, in Enterprise COBOL, the compiler generates an extra little area, copies the first argument to that area, tests against the second argument, copies the copy of the first argument, or the second argument, whichever is relevant, to the result.
Vs the ELSE, that is an extra storage area defined, an extra instruction for addressability of that, and an extra Assembler move (MVC) plus the lack of ready recognition.
Better for programmers new to COBOL, used to a multitude of functions in other languages? Not really, as they will be soundly beaten if they don't write programs that can be understood (at 2am) by the rest of the staff.
IF FUNCTION MIN(VAR1 VAR2 VAR3 VAR4 VAR5) = 17
It's another downside of FUNCTION. You see, you can do that. Then, at 2am, when the program has crashed 32 lines later, after VAR1 and VAR3 have been changed, are you going to be able to find the result of that IF in the core dump? Maybe, maybe not. Depends if any other functions, and of what type, have been used. At 2am, you don't want that. Not at all.
On the upside, it is less typing. For those who type, rather than use the editor.
In our shop, we'd use the example provided by Bill Woodger. However, we do use periods as scope-terminators. COBOL should be structured and use the KISS principle, just like any other language. This:
MOVE SECOND TO WS.
IF FIRST LESS THAN SECOND
MOVE FIRST TO WS.
MOVE WS TO RESULT.
Note that this only works if we are assured that SECOND and FIRST have numeric values, or that WS is a PIC X() string, not a numeric PIC 9().
This is by far the easiest to read. No ELSE or GO TO required.
I'm making a web app where the point is to change a given word by one letter. For example, if I make a post by selecting the word: "best," then the first reply could be "rest," while the one after that should be "rent," "sent", etc. So, the word a user enters must have changed by one letter from the last submitted word. It would be constantly evolving.
Right now you can make a game and respond just by typing a word. I coded up a custom validation using functionality from the Amatch gem:
http://flori.github.com/amatch/doc/index.html
Posts have many responses, and responses belong to a post.
here's the code:
def must_have_changed_by_one_letter
m = Amatch::Sellers.new(title.strip)
errors.add_to_base("Sorry, you must change the last submitted word by one letter")
if m.match(post.responses.last.to_s.strip) != 1.0
end
When I try entering a new response for a test post I made (original word "best", first response is "rest") I get this:
ActiveRecord::RecordInvalid in ResponsesController#create
Validation failed: Sorry, you must change the last submitted word by one letter
Any thoughts on what might be wrong?
Thanks!
Looks like there are a couple of potential issues here.
For one, is your if statement actually on a separate line than your errors.add_to_base... statement? If so, your syntax is wrong; the if statement needs to be in the same line as the statement it's modifying. Even if it is actually on the correct line, I would recommend against using a trailing if statement on such a long line; it will make it hard to find the conditional.
if m.match(post.responses.last.to_s.strip) != 1.0
errors.add_to_base("Sorry, you must change the last submitted word by one letter")
end
Second, doing exact equality comparison on floating point numbers is almost never a good idea. Because floating point numbers involve approximations, you will sometimes get results that are very close, but not quite exactly equal, to a given number that you are comparing against. It looks like the Amatch library has several different classes for comparing strings; the Sellers class allows you to set different weights for different kinds of edits, but given your problem description, I don't think you need that. I would try using the Levenshtein or Hamming distance instead, depending on your exact needs.
Finally, if neither of those suggestions work, try writing out to a log or in the response the exact values of title.strip and post.responses.last.to_s.strip, to make sure you are actually comparing the values that you think you're comparing. I don't know the rest of your code, so I can't tell you whether those are correct or not, but if you print them out somewhere, you should be easily able to check them yourself.