> I tried using adverse. For me it was a miserable failure - I didn't > realize that (u y)::(error yy) was probably returning nouns, while adverse > wants verbs as you showed. I have not tried using generated errors. What > is fun about this language, for me, is that scutwork (coding loops to > compare arrays or to move arrays) vanishes, while you can concentrate on > the logic of your program.
The following adverb Trap and the associated verb Trigger are based on adverse. u Trap behaves as u if no error is generated; if Trigger is executed while v is running then u produces immediately the argument of Trigger; if another kind of error occurs it is simply reported. All this assumes that there are no other :: involved. Trap and Trigger are fixed and tacit (and Trigger is unorthodox (wicked)) but they could be rewritten explicitly and compliantly (with the usual caveats). They were meant to be used in a tacit setup but I do not see any reason why they could not work in a general setup; however, they have not been tested much and a defect is a potential interference with other :: . Actually, Trap and Trigger were prototypes for primitives of a fork of J which can be discussed only in the Chat Forum (see, http://www.jsoftware.com/pipermail/programming/2017-November/049516.html). I hope this is helpful: o=. @: c=. "_ ErrNum=. (13!:11) ErrMsg=. (13!:12) o (''c) NB. (e.g., ErrMsg '' ) Trap=. ::(ErrMsg f.@:(''"_)`(".@:('R_Trap_'"_))@.(255 -: ErrNum f.@ :(''"_))) SignalErr=. 13!:8 NB. Signal error number rank=. (;:'"')(0:`)(,^:) NB. Verbing " (dyadic verb) lrw=. (_2 }. ":) o (rank&_) NB. Linear representation (monadic verb) k=. ] [ (". o ([ , '=. ' , lrw @:])) NB. Keep (monadic verb) Trigger=. SignalErr o (255 c) o ('R_Trap_'&k) f. NB. (monadic verb) NB. Testing... < o % Trap 1 2 3 ┌──────────────┐ │1 0.5 0.333333│ └──────────────┘ < o % Trap '...' |domain error | <o%Trap'...' |[-18] < o Trigger o *: Trap 1 2 3 1 4 9 < o Trigger o ('It seems to work...'c) Trap 1 2 3 It seems to work... On Fri, Jan 5, 2018 at 6:26 PM, Nick S <[email protected]> wrote: > Great suggestion. I actually played with it for quite a while last night, > got it all working. The solver can solve any puzzle I throw at it, > including those that barely have enough definition to hold together. I can > imagine puzzles it can't solve but those would have to be constructed to be > unsolvable. > > I ended up using a lot of throws and trys and such. In some cases, the > only exit from a routine is a set of throws with flag variables set, as in > the example, to communicate, and it took a heck of a lot of code. In fact, > when I start the project, it takes way longer than it used to because there > is just way too much procedural code. > > I wonder just how expensive try. is. I used to get solutions in the under > 2 second range. Now I am getting solutions in the 3.5 second range. But > this seems to be totally based on the amount of processing. My first > solutions were solved without trial placement or backtracking, but the long > solutions require trial placement and backtracking. I just checked one of > my old testcases and it is still under 2 seconds cpu for a solution. > > I also have hand coded backtracking, so that I can execute a trial solution > and easily give it up when it goes nowhere. > > J makes it easy to create relatively complex data structures (like stacks > for backtracking environments). I ended up with a lot of code but most > other languages would have required five times as much code. > > My basic concept was that I kept a recursion count. and in my try./catcht/ > I used the entry level to control what I did - generally at any level where > I recursed, I would just throw. again and at the entry level I would put > out an error message and then return. So I don't get error messages when I > pick up the uncaught throw. Now I am catching all my throws and always > reporting errors or successes from the top level. > > I appreciate all the advice I got while writing this. I will work on it a > bit more to clean up the messages and any other bugs I find. But I have > entered about 15 test cases, and it seems to be able to solve them all. > > I have used a lot of if-then-else and case logic. I know, I should be > writing all this stuff as tacit one liners. But I don't see how. For > example, given the length of a boolean vector as 20, is there a way to > return all of the possible placements of three groups of 1's with length > of 3, 4, and 5, always in that order, and with at least one zero between > them? There can be zero or more zeros between the placements and the wall. > In other words, all the vectors that, when converted to a character string, > match this regular expression: > > ^0*1{3}0+1{4}0+1{5}0*$ > > 0 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0 matches > > 1 1 1 1 0 0 0 1 1 1 1 0 1 1 1 1 1 0 0 0 does not. The first group is too > long. There are a very large number of possible wrong solutions, but there > are also a large number of valid solutions. > > I could not figure out how to do it - so I ended up writing a recursive > routine where I place the first piece and then pass the rest of the work (a > shortened string and fewer placements) to the recursive call. The routine > has the advantage of letting me do early pruning of solutions where what I > have already placed violates constraints, and so forth. And I never have > to generate a huge binary table, just to filter and compress it to get the > results that I need for the solution. > > I tried using adverse. For me it was a miserable failure - I didn't > realize that (u y)::(error yy) was probably returning nouns, while adverse > wants verbs as you showed. I have not tried using generated errors. What > is fun about this language, for me, is that scutwork (coding loops to > compare arrays or to move arrays) vanishes, while you can concentrate on > the logic of your program. > > > > On Sun, Dec 31, 2017 at 11:28 AM, Ian Clark <[email protected]> wrote: > > > What's "normal" and what's an "error"? (Or, for that matter, a "crash"?) > > > > When looking for the best solution to a coding problem, we can be > prisoners > > of our emotive use of language. Way back in IBM in the 1980s I recall the > > end-user of a bespoke app written in APL picking up the phone in fury > when > > it spat out at her the all-too-familiar APL message: > > RANK ERROR > > – she thought the coder was being gratuitously offensive. > > > > Stripped of its pejorative connotations, error recovery is just a way of > > letting a deeply nested function escape and cut back the function stack – > > and to do it in a way that doesn't look to the end-user like a coding > > error. Or conversely, treating her to the sight of a raw coding error > when > > she'd appreciate a polite message geared to her needs and competency. > > > > I use (::) a lot for this purpose. Far from being "ugly" I think it is > > clean and respectable, avoiding the need for (…but not precluding) a > > cumbersome system of error diagnostics – which then needs debugging in > its > > own right. > > > > It also establishes a clear separation between "normal" code and > > special-case handling (including error recovery), which lets you design > the > > former and then bolt-on as much of the latter as you need, and no more — > > which to my mind (try./catch.) doesn't. > > > > Paste this into a temp script and run it: > > ———————————————————————————————————————— > > > > NB. Use of (::) to escape to the session in a clean and respectable way. > > > > NB. Avoid tainting the escape route with disapproval > > > > NB. by using "general" not "normal" and "special" not "error". > > > > > > myApp=: general :: special > > > > general=: verb define > > general1 y > > ) > > > > general1=: verb define > > NB. nest it deeper > > addOne y > > ) > > > > addOne=: verb define > > NB. recognise special cases... > > if. y<0 do. @@ end. > > if. y>99 do. @@ end. > > NB. else handle the general case... > > y+1 > > ) > > > > special=: verb define > > 'myApp: cannot handle the argument: ' , ":y > > ) > > ———————————————————————————————————————— > > > > Running the app… > > > > myApp 5 NB. handles general case ok > > 6 > > myApp _5 NB. rejects y<0 > > myApp: cannot handle the argument: _5 > > myApp 100 NB. rejects y>99 > > myApp: cannot handle the argument: 100 > > myApp '?' NB. forces a syntax error > > myApp: cannot handle the argument: ? > > > > Now, crashing (general) by executing (@@) is not everyone's idea of > "clean > > and respectable". But worse – you can't tell a deliberate crash from an > > accidental one, as (myApp'?') shows. > > > > However instead of (@@) you can signal a quasi-error with your own > private > > error number, and progressively code just the error diagnostics you need > > into verb: (special) to report any bona-fide coding errors you haven't > > fixed yet. > > > > NuVoc explains how: > > > > http://code.jsoftware.com/wiki/Vocabulary/ErrorMessages#Defi > > ning_your_own_error_conditions > > > > Thus you could redefine (addOne) and (special) like this… > > > > ———————————————————————————————————————— > > addOne=: verb define > > NB. recognise special cases... > > if. y<0 do. signalErrorNumber 255 end. > > if. y>99 do. signalErrorNumber 99 end. > > NB. else handle the general case... > > y+1 > > ) > > > > special=: verb define > > select. latestErrorNumber'' > > case. 99 do. 'myApp: cannot handle y>99: ' , ":y > > case. 255 do. 'myApp: cannot handle y<0: ' , ":y > > case. do. latestErrorMessage'' > > end. > > ) > > > > signalErrorNumber=: 13!:8 > > latestErrorNumber=: 13!:11 > > latestErrorMessage=: 13!:12 > > ———————————————————————————————————————— > > > > Now running the app… > > > > myApp 5 NB. handles general case ok > > 6 > > myApp _5 NB. rejects y<0 > > myApp: cannot handle y<0: _5 > > myApp 100 NB. rejects y>99 > > myApp: cannot handle y>99: 100 > > myApp '?' NB. forces a coding error > > |domain error: addOne > > | y <0 > > > > > > > > > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
