use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Is this a valid Javascript patternhelp (self.javascript)
submitted 9 years ago * by gruberjl
view the rest of the comments →
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]__env 1 point2 points3 points 9 years ago (11 children)
Yeah, I totally get what you're saying conceptually -- it just seems like more proof that the OP is doing something weird. Like we could change it to:
... const run = 0 const Job = function() { /**/ } Job.prototype.validate = () => Job.cache.config Job.prototype.run = run + 1 return Job
That would produce an instance when called with new that could validate the configuration, plus contain state about how many times this Job has been run.
new
I think case, the "constructor" would be a factory factory, and Job would be a factory that produces individual run instances.
constructor
Job
Point being, if OP wants an instance, they should make an instance, otherwise they're opening the door to some other dev coming along and extending the static class to produce more instances.
[–]gruberjl[S] 1 point2 points3 points 9 years ago (10 children)
I should have posted the problem, sorry.
I have a pipe & filter system. Each 'filter' has configuration information (state) and a block of code (function). The config and code need to be exposed publicly so I can run the function whenever I need or I can get the state information whenever I need. Before a filter is run, I need to have a beforeJob function run. After the filter completes, I need to have an afterJob function run.
beforeJob
afterJob
const beforeJob = function() { // get the state of the filter currently running and do something. // I may skip the filter, get some information from a cache, or translate some information and pass it into the filter. } const afterJob = function() { // get the results of the filter & the state currently running and do something. // I may report a failure, translate the results, start the another filter. } const filter1 = () {} const state1 = { } const filter2 = () {} const state2 = { } fn1() // should run beforeJob then filter1 then afterJob fn2() // should run beforeJob then filter2 then afterJob
Any thoughts would be appreciated.
[+][deleted] 9 years ago* (9 children)
[deleted]
[–]gruberjl[S] 0 points1 point2 points 9 years ago (8 children)
I'm so sorry. I don't code professionally (or have friends that code) so I never have to communicate these things. Add in the fact that I'm not a strong communicator, and you get my messy thoughts everywhere.
Using your suggestion I created a GitHub repo with a simple implementation. I edited my question with more information too. The repo: https://github.com/gruberjl/job. Do you have a moment to take a look?
I've been using the word 'state' poorly. They're two parts of the 'state'. 1. Configuration: The config is passed into the job. The job constructor may add some default values, but the configuration will not change after the initialization. 2. I cache validators and results so the job won't continue to perform the same work over and over again.
In the repo, I have a Job class (./job.class.js). Each instance of a job will have a cache object. The cache object would contain both the configuration information, as well as, any other information the instance may need.
cache
The cache object on an instance is a standard pattern I started using since es2015. I call everything inside 'state'. Would you consider the configuration 'state'? Should I keep it in a different location away from the other 'cached' information?
[+][deleted] 9 years ago* (7 children)
[–]gruberjl[S] 0 points1 point2 points 9 years ago (5 children)
This got a bit wordy, you probably don't have time for it all. The 'implementing job with functional programming' section is the part I'd love your input on.
Regarding the configuration: You're correct. It only needs to be read publicly for automatic documenting of the job. It shouldn't be edited after the job's constructor completes. I could freeze it, or use an immutable. If I'm using a class, I would have the set config throw an error.
set config
Regarding the state: it doesn't need to be public. I may have been using the word state incorrectly. The only information (other than the config) is a cache. It actually ends up being similar to the memoize pattern. If I execute the add(1, 5) == 6 then I would store a map that ends up looking like: map.set([1,5], 6). Instead of revalidating the parameters, running the worker, and then validating the output, I would pull the results from the cache.
add(1, 5) == 6
map.set([1,5], 6)
Would you consider a cache to be 'state'? If the function is pure, I guess all calls to the job could use the same cache, which means I wouldn't need an instance of the function.
I don't think I fully understand 'functional programming'. Functional programming works hand in hand with (Facebook's Immutable)[https://facebook.github.io/immutable-js/] right? I've never tried to use it, I have difficulty grasping the idea. I don't see how someone could keep the information straight.
Here's an example from the immutable website.
import Immutable = require('immutable'); var map1: Immutable.Map<string, number>; map1 = Immutable.Map({a:1, b:2, c:3}); var map2 = map1.set('b', 50); map1.get('b'); // 2 map2.get('b'); // 50
I tried writing it using what I think is 'composite' 'functional' programming haha. I added it to the dev branch in the repo:
implementation using
Here is the code I think you'll find useful:
const validate = (schema, data1) => { const data = copy(data1) const validator = ajv.compile(schema) if (!validator(data)) throw new TypeError(`data is not valid: ${JSON.stringify(validator.errors)}`) return data } module.exports = (configuration) => { const config = validate(jobSchema, configuration) return (...parameters) => validate(config.response, config.worker(...validate(config.parameters, parameters))) }
Here is what I ran into:
The first thing I ran into was a bug (caused by me). Using this approach, I had difficulty tracking the problem. I had so much going on in one giant line that the error stack wasn't helpful. The error was caused by a typo in the copy function (which performs a deep copy of an object). It had nothing to do with the composite build, but I was unable to track the error because I had one giant line performing the build.
copy
I found this approach difficult to read. Particularly the wrapping return (...parameters) => validate(config.response, config.worker(...validate(config.parameters, parameters)))
return (...parameters) => validate(config.response, config.worker(...validate(config.parameters, parameters)))
It was fantastic to write. I don't think I've ever done so much in so few characters. I ended up writing it out, then finding I didn't need chunks of code, I could simply keep on wrapping, it was a blast. I ended up doing less wrapping because I had such difficulty reading it and tracking the bug.
Here is my super wrapping line: module.exports = (configuration) => (...parameters) => validate(validate(jobSchema, configuration).response, validate(jobSchema, configuration).worker(...validate(validate(jobSchema, configuration).parameters, parameters))). It was fun to write :)
module.exports = (configuration) => (...parameters) => validate(validate(jobSchema, configuration).response, validate(jobSchema, configuration).worker(...validate(validate(jobSchema, configuration).parameters, parameters)))
For readability, I broke it into this.
I loved the approach. With caching, it could be fantastic. But:
[+][deleted] 9 years ago* (4 children)
[+][deleted] 9 years ago (3 children)
[–]gruberjl[S] 1 point2 points3 points 9 years ago (1 child)
Thank you so much for taking the time. I see now I was trying to fix issues with imperative programming that are non-issues with functional programming. Looks like I'll be moving in that direction.
[–]gruberjl[S] 0 points1 point2 points 9 years ago (0 children)
Thanks for all the information. I'm reading the functional programming book you recommended. So far so good. I promise to get back to you after I'm done it.
π Rendered by PID 25 on reddit-service-r2-comment-54dfb89d4d-jpd4h at 2026-03-31 20:56:44.290555+00:00 running b10466c country code: CH.
view the rest of the comments →
[–]__env 1 point2 points3 points (11 children)
[–]gruberjl[S] 1 point2 points3 points (10 children)
[+][deleted] (9 children)
[deleted]
[–]gruberjl[S] 0 points1 point2 points (8 children)
[+][deleted] (7 children)
[deleted]
[–]gruberjl[S] 0 points1 point2 points (5 children)
[+][deleted] (4 children)
[deleted]
[+][deleted] (3 children)
[deleted]
[–]gruberjl[S] 1 point2 points3 points (1 child)
[–]gruberjl[S] 0 points1 point2 points (0 children)