Fork me on GitHub
#malli
<
2021-03-08
>
borkdude10:03:56

user=> (time (m/validate [:cat [:+ [:+ [:enum 0]]] [:enum 1]] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]) )
"Elapsed time: 0.582137 msecs"
true
user=> (time (s/valid? (s/cat :zeroes (s/+ (s/+ #{0})) :one #{1}) [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]))
"Elapsed time: 1265.3679 msecs"
(got the example from https://quanttype.net/posts/2021-03-06-clojure-spec-and-untrusted-input.html)

borkdude10:03:56

Are there any examples of regexes that are slow in malli too?

miikka10:03:21

Malli's regular expression matching algorithm is fundamentally different, so as far as i know, it does not have the exponential slow down problem. Probably you could still come up with some slow examples, but I don't have insight into what is slow and what is fast.

borkdude10:03:41

Because it doesn't have backtracking, right?

miikka13:03:41

It does use backtracking, but see the ns docstring for discussion: https://github.com/metosin/malli/blob/master/src/malli/impl/regex.cljc

arundilipan15:03:09

Sorry for the late response @borkdude @ikitommi, I had an health emergency this week and so I wasn’t able to do anything about it

arundilipan15:03:18

I did follow up with the example and it did work

arundilipan15:03:52

I have a follow-up question, though

arundilipan15:03:16

I’m wondering if m/decode with the above schema is supposed to produce that result, and if so, I was wondering how to solve this so that I return [1.0 "A"] from decode?

ikitommi17:03:08

@arundilipan works on my machine:

(ns sample.core
  (:require [malli.core :as m]
            [malli.transform :as mt]))

(def GreaterThanZero
  [:fn {:decode/string mt/-string->double}
   '#(> % 0)])

(def TestEnum
  [:enum "A" "B"])

(m/decode
  [:catn
   [:amount GreaterThanZero]
   [:layout TestEnum]]
  ["1.0" "A"]
  mt/string-transformer)
; => [1.0 "A"]

ikitommi17:03:31

if the result doesn’t match the schema after the transformation, the top-level schema returns the original. this is a feature of the current regex impl, doesn’t support partial transformation:

(m/decode
  [:catn
   [:amount GreaterThanZero]
   [:layout TestEnum]]
  ["1.0" "C"]
  mt/string-transformer)
; => ["1.0" "C"]

arundilipan17:03:23

Oh that’s it, you’re right

arundilipan17:03:51

In that case I guess the thing to do would be do use something like edn/read-string instead of decode? I’d like to make sure that the number is parsed regardless of the result of the rest of the :catn

ikitommi17:03:57

or, you could use non-regex schema like :tuple:

(m/decode
  [:tuple GreaterThanZero TestEnum]
  ["1.0" "C"]
  mt/string-transformer)
; => [1.0 "C"]

ikitommi17:03:10

no :tuplen atm 😉

ikitommi17:03:16

you could write issue about the partial decoding with regex?

ikitommi17:03:53

(might be easy to fix)

arundilipan17:03:14

Yea i’ll make an issue on the repo

arundilipan17:03:31

Right now I’m trying to use the :catn variants because of the coercion into a map