@@ -292,6 +292,177 @@ def test_result_apply_chain():
292292 )
293293
294294
295+ def test_result_method_chain ():
296+ from math import sqrt
297+
298+ def div (numerator , denominator ):
299+ return numerator / denominator
300+
301+ def plus11 (x , * args ):
302+ # *args not used, but needed because apply_or_else(efunc, ofunc) requires
303+ # both functions to have the same arg length, see `apply_or_else(plus11, div, 0)` or `.apply_or_else(plus11, div, 2)`
304+ return x + 11
305+
306+ def pow2 (x ):
307+ return x ** 2
308+
309+ def neg (x , * args ):
310+ # *args not used, but needed because apply_or_else(efunc, ofunc) requires
311+ # both functions to have the same arg length, see `.apply_or_else(neg, div, 0)`
312+ return - x
313+
314+ a = Ok (5 )
315+
316+ with pytest .raises (ValueError ):
317+ fail1 = a .map (pow2 ).map (plus11 ).map (sqrt ).map (neg ).map (sqrt )
318+ # 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
319+
320+ with pytest .raises (ValueError ):
321+ fail2 = a .map (pow2 ).map (plus11 ).map (sqrt ).map (neg ).map_or (None , sqrt )
322+ # 5 -> 25 -> 36 -> 6 -> -6 -> raise ValueError
323+
324+ b = (
325+ a .apply (pow2 ) # Ok(5) -> Ok(25)
326+ .apply (plus11 ) # -> Ok(36)
327+ .apply (sqrt ) # -> Ok(6)
328+ .apply (neg ) # -> Ok(-6)
329+ .apply (sqrt ) # -> Err("Result.apply exception | ValueError: math domain error")
330+ )
331+
332+ c = (
333+ a .apply (pow2 ) # Ok(5) -> Ok(25)
334+ .apply (plus11 ) # -> Ok(36)
335+ .apply (sqrt ) # -> Ok(6)
336+ .apply (neg ) # -> Ok(-6)
337+ .apply_or (None , sqrt ) # -> Ok(None)
338+ )
339+
340+ d = (
341+ a .apply (pow2 ) # Ok(5) -> Ok(25)
342+ .apply (plus11 ) # -> Ok(36)
343+ .apply (sqrt ) # -> Ok(6)
344+ .apply (neg ) # -> Ok(3)
345+ .apply_or_else (plus11 , sqrt ) # -> Ok(5)
346+ )
347+
348+ e = (
349+ a .apply (pow2 ) # Ok(5) -> Ok(25)
350+ .apply (plus11 ) # -> Ok(36)
351+ .apply (sqrt ) # -> Ok(6)
352+ .apply (div , 2 ) # -> Ok(3)
353+ .apply (div , 0 ) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
354+ )
355+ # 5 -> 25 -> 36 -> 6 -> 3 -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
356+
357+ f = (
358+ a .apply (pow2 ) # Ok(5) -> Ok(25)
359+ .apply (plus11 ) # -> Ok(36)
360+ .apply (sqrt ) # -> Ok(6)
361+ .apply (div , 2 ) # -> Ok(3)
362+ .apply_or_else (plus11 , div , 0 ) # -> Ok(14)
363+ )
364+
365+ g = (
366+ a .apply (pow2 ) # Ok(5) -> Ok(25)
367+ .apply (plus11 ) # -> Ok(36)
368+ .apply (sqrt ) # -> Ok(6)
369+ .apply_or_else (neg , div , 0 ) # -> Ok(-6)
370+ .apply_or_else (plus11 , div , 2 ) # -> Ok(-3)
371+ )
372+
373+ assert a .is_Ok and a == Ok (5 )
374+ assert b .is_Err and b .Err_msg_contains ("ValueError" )
375+ assert c .is_Ok and c == Ok (None )
376+ assert d .is_Ok and d == Ok (5 )
377+ assert e .is_Err and e .Err_msg_contains ("ZeroDivisionError" )
378+ assert f .is_Ok and f == Ok (14 )
379+ assert g .is_Ok and g == Ok (- 3 )
380+
381+
382+ def test_result_method_chain_lambda ():
383+ from math import sqrt
384+ # div = lambda x, y: x / y
385+ # plus11 = lambda x: x + 11
386+ # pow2 = lambda x: x**2
387+ # neg = lambda x: -x
388+
389+ a = Ok (5 )
390+
391+ with pytest .raises (ValueError ):
392+ fail1 = (
393+ a .map (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
394+ .map (lambda x : x + 11 ) # -> Ok(36)
395+ .map (sqrt ) # -> Ok(6)
396+ .map (lambda x : - x ) # -> Ok(-6)
397+ .map (sqrt ) # -> raise ValueError
398+ )
399+
400+ with pytest .raises (ValueError ):
401+ fail2 = (
402+ a .map (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
403+ .map (lambda x : x + 11 ) # -> Ok(36)
404+ .map (sqrt ) # -> Ok(6)
405+ .map (lambda x : - x ) # -> Ok(-6)
406+ .map_or (None , sqrt ) # -> raise ValueError
407+ )
408+
409+ b = (
410+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
411+ .apply (lambda x : x + 11 ) # -> Ok(36)
412+ .apply (sqrt ) # -> Ok(6)
413+ .apply (lambda x : - x ) # -> Ok(-6)
414+ .apply (sqrt ) # -> Err("Result.apply exception | ValueError: math domain error")
415+ )
416+
417+ c = (
418+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
419+ .apply (lambda x : x + 11 ) # -> Ok(36)
420+ .apply (sqrt ) # -> Ok(6)
421+ .apply (lambda x : - x ) # -> Ok(-6)
422+ .apply_or (None , sqrt ) # -> Ok(None)
423+ )
424+
425+ d = (
426+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
427+ .apply (lambda x : x + 11 ) # -> Ok(36)
428+ .apply (sqrt ) # -> Ok(6)
429+ .apply (lambda x : - x ) # -> Ok(-6)
430+ .apply_or_else (lambda x : x + 11 , sqrt ) # -> Ok(5)
431+ )
432+
433+ e = (
434+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
435+ .apply (lambda x : x + 11 ) # -> Ok(36)
436+ .apply (sqrt ) # -> Ok(6)
437+ .apply (lambda x , y : x / y , 2 ) # -> Ok(3)
438+ .apply (lambda x , y : x / y , 0 ) # -> Err("Result.apply exception | ZeroDivisionError: float division by zero")
439+ )
440+
441+ f = (
442+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
443+ .apply (lambda x : x + 11 ) # -> Ok(36)
444+ .apply (sqrt ) # -> Ok(6)
445+ .apply (lambda x , y : x / y , 2 ) # -> Ok(3)
446+ .apply_or_else (lambda x , y : x + 11 , lambda x , y : x / y , 0 ) # -> Ok(14)
447+ )
448+
449+ g = (
450+ a .apply (lambda x : x ** 2 ) # Ok(5) -> Ok(25)
451+ .apply (lambda x : x + 11 ) # -> Ok(36)
452+ .apply (sqrt ) # -> Ok(6)
453+ .apply_or_else (lambda x , y : - x , lambda x , y : x / y , 0 ) # -> Ok(-6)
454+ .apply_or_else (lambda x , y : x + 11 , lambda x , y : x / y , 2 ) # -> Ok(-3)
455+ )
456+
457+ assert a .is_Ok and a == Ok (5 )
458+ assert b .is_Err and b .Err_msg_contains ("ValueError" )
459+ assert c .is_Ok and c == Ok (None )
460+ assert d .is_Ok and d == Ok (5 )
461+ assert e .is_Err and e .Err_msg_contains ("ZeroDivisionError" )
462+ assert f .is_Ok and f == Ok (14 )
463+ assert g .is_Ok and g == Ok (- 3 )
464+
465+
295466# Arithmetic Operator Overloading
296467def test_addition ():
297468 result1 = Ok (10 )
0 commit comments