This talk describes refactoring FindBin::libs from Perl5 to Raku: breaking the module up into functional pieces, writing the tests using Raku, testing and releasing the module with mi6.
The $path to knowledge: What little it take to unit-test Perl.Workhorse Computing
Metadata-driven lazyness, Perl, and Jenkins provide a nice mix for automated testing. With Perl the only thing required to start testing is a files path, from there the possibilities are endless. Using Symbol's qualify_to_ref makes it easy to validate @EXPORT & @EXPORT_OK, knowing the path makes it easy to use "perl -wc" to get diagnostics.
The beautiful thing is all of it can be lazy... er, "automated". And repeatable. And simple.
Variable interpolation is a standard way to BASH your head. This talk looks at interpolation, eval, ${} handling and "set -vx" to debug basic variable handling.
Face it, backticks are a pain. BASH $() construct provides a simpler, more effective approach. This talk uses examples from automating git branches and command line processing with getopt(1) to show how $() works in shell scripts.
We have all seen repetitive code, maintained by cut+paste, that creates an object, calls a method, checks a return, calls a method, checks a return... all of it difficult to maintain because of its sheer size.
Object::Exercise replaces the pasted loops with data-driven code, the operation controlled by a data structure of methods, arguments, and expected return values. This replaces cut+paste with declarative data.
This talk describes O::E and shows a few ways to apply it for testing the MadMongers' Adventure game.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
Overview of Trampoline Objects in Perl with examples for lazy construction, lazy module use, added sanity checks. This version includes corrections from the original presented at OSCON 2013 and comments.
Starting with the system calll "getrusage", this returns synchronous, process-level information, mainly max RSS used. This talk describes the output from getrusage, the rusage formatting utility in ProcStats, and several examples of using it to examine time and memory use.
Optional first & final outputs to give baseline and total status, differencing avoids extraneous output, and user messages allow arbitrary stat's and tracking content.
The combination makes this nice for tracking both long-lived and shorter, more intensive processing.
The $path to knowledge: What little it take to unit-test Perl.Workhorse Computing
Metadata-driven lazyness, Perl, and Jenkins provide a nice mix for automated testing. With Perl the only thing required to start testing is a files path, from there the possibilities are endless. Using Symbol's qualify_to_ref makes it easy to validate @EXPORT & @EXPORT_OK, knowing the path makes it easy to use "perl -wc" to get diagnostics.
The beautiful thing is all of it can be lazy... er, "automated". And repeatable. And simple.
Variable interpolation is a standard way to BASH your head. This talk looks at interpolation, eval, ${} handling and "set -vx" to debug basic variable handling.
Face it, backticks are a pain. BASH $() construct provides a simpler, more effective approach. This talk uses examples from automating git branches and command line processing with getopt(1) to show how $() works in shell scripts.
We have all seen repetitive code, maintained by cut+paste, that creates an object, calls a method, checks a return, calls a method, checks a return... all of it difficult to maintain because of its sheer size.
Object::Exercise replaces the pasted loops with data-driven code, the operation controlled by a data structure of methods, arguments, and expected return values. This replaces cut+paste with declarative data.
This talk describes O::E and shows a few ways to apply it for testing the MadMongers' Adventure game.
Object Trampoline: Why having not the object you want is what you need.Workhorse Computing
Overview of Trampoline Objects in Perl with examples for lazy construction, lazy module use, added sanity checks. This version includes corrections from the original presented at OSCON 2013 and comments.
Starting with the system calll "getrusage", this returns synchronous, process-level information, mainly max RSS used. This talk describes the output from getrusage, the rusage formatting utility in ProcStats, and several examples of using it to examine time and memory use.
Optional first & final outputs to give baseline and total status, differencing avoids extraneous output, and user messages allow arbitrary stat's and tracking content.
The combination makes this nice for tracking both long-lived and shorter, more intensive processing.
A short introduction to the perl debugger's basic commands for executing code, examining data structures. Includes examples of hardwiring breakpoints, tracing sections of code, debugging regexen.
Building a Perl5 smoketest environment in Docker using CPAN::Reporter::Smoker. Includes an overview of "smoke testing", shell commands to contstruct a hybrid environment with underlying O/S image and data volumes for /opt, /var/lib/CPAN. This allows maintaining the Perly smoke environemnt without having to rebuild it.
Perl6 regular expression ("regex") syntax has a number of improvements over the Perl5 syntax. The inclusion of grammars as first-class entities in the language makes many uses of regexes clearer, simpler, and more maintainable. This talk looks at a few improvements in the regex syntax and also at how grammars can help make regex use cleaner and simpler.
perl often doesn't get updated because people don't have a way to know if their current code works with the new one. The problem is that they lack unit tests. This talk describes how simple it is to generate unit tests with Perl and shell, use them to automate solving problems like missing modules, and test a complete code base.
Short introduction to the basics of Perl testing and some resources for further reading. Includes basics of Test::Simple, Test::More, using Inline for multi-language testing, testing coverage, testing tests.
Perl6 introduces a variety of tools for functional programming and writing readable code. Among them parameter declarations and lazy lists. This talk looks at how to get Perl6, where to find examples on RakudoCode, and how to use Perl6 functional tools for converting an algorithm from imperative to functional code, including parallel dispatch with the ">>" operator.
The Perforce Web Content Management System development team, lacking a pre-existing solution in PHP, designed and implemented their own object model and record layer to ease the interaction of the system with the Perforce Server. This session will focus on how users can access files in Perforce via a simple CRUD API, the subsystems exposed, and their usage.
Complet vector.dep.inc# This code depends on make tool being .docxardhowp
Complet vector/.dep.inc
# This code depends on make tool being used
DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES} ${TESTOBJECTFILES}))
ifneq (${DEPFILES},)
include ${DEPFILES}
endif
Complet vector/build/Debug/Cygwin-Windows/main.o
Complet vector/build/Debug/Cygwin-Windows/main.o.d
build/Debug/Cygwin-Windows/main.o: main.cpp SimpleVector.h
SimpleVector.h:
Complet vector/dist/Debug/Cygwin-Windows/complet_vector.exe
Complet vector/main.cppComplet vector/main.cpp/*
* File: main.cpp
* Author: Bebo
* Created on April 8, 2019, 6:18 PM
* Purpose:Complex Vector
*/
#include<cstdlib>
#include"SimpleVector.h"
//System Libraries
#include<iostream>//Input/Output Library
usingnamespace std;
//User Libraries
//Global Constants, no Global Variables are allowed
//Math/Physics/Conversions/Higher Dimensions - i.e. PI, e, etc...
//Function Prototypes
void fillVec(SimpleVector<int>&);
void addVec(SimpleVector<int>&);
void delVec(SimpleVector<int>&);
void prntVec(SimpleVector<int>&,int);
//Execution Begins Here!
int main(int argc,char** argv){
//Declare Variables
int size;
//Read in the size
cout<<"What size vector to test?"<<endl;
cin>>size;
SimpleVector<int> sv(size);
//Initialize or input i.e. set variable values
fillVec(sv);
//Display the outputs
prntVec(sv,10);
//Add and subtract from the vector
addVec(sv);
//Display the outputs
prntVec(sv,10);
//Add and subtract from the vector
delVec(sv);
//Display the outputs
prntVec(sv,10);
//Exit stage right or left!
return0;
}
void addVec(SimpleVector<int>&sv){
int add=sv.size()*0.1;
for(int i=1;i<=add;i++){
sv.push_front(i+add-1);
sv.push_back(i-add);
}
}
void delVec(SimpleVector<int>&sv){
int del=sv.size()*0.2;
for(int i=1;i<=del;i++){
sv.pop_front();
sv.pop_back();
}
}
void fillVec(SimpleVector<int>&sv){
for(int i=0;i<sv.size();i++){
sv[i]=i%10;
}
}
void prntVec(SimpleVector<int>&sv,int n){
cout<<endl;
for(int i=0;i<sv.size();i++){
cout<<sv[i]<<" ";
if(i%n==(n-1))cout<<endl;
}
cout<<endl;
}
Complet vector/Makefile
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed dire.
A short introduction to the perl debugger's basic commands for executing code, examining data structures. Includes examples of hardwiring breakpoints, tracing sections of code, debugging regexen.
Building a Perl5 smoketest environment in Docker using CPAN::Reporter::Smoker. Includes an overview of "smoke testing", shell commands to contstruct a hybrid environment with underlying O/S image and data volumes for /opt, /var/lib/CPAN. This allows maintaining the Perly smoke environemnt without having to rebuild it.
Perl6 regular expression ("regex") syntax has a number of improvements over the Perl5 syntax. The inclusion of grammars as first-class entities in the language makes many uses of regexes clearer, simpler, and more maintainable. This talk looks at a few improvements in the regex syntax and also at how grammars can help make regex use cleaner and simpler.
perl often doesn't get updated because people don't have a way to know if their current code works with the new one. The problem is that they lack unit tests. This talk describes how simple it is to generate unit tests with Perl and shell, use them to automate solving problems like missing modules, and test a complete code base.
Short introduction to the basics of Perl testing and some resources for further reading. Includes basics of Test::Simple, Test::More, using Inline for multi-language testing, testing coverage, testing tests.
Perl6 introduces a variety of tools for functional programming and writing readable code. Among them parameter declarations and lazy lists. This talk looks at how to get Perl6, where to find examples on RakudoCode, and how to use Perl6 functional tools for converting an algorithm from imperative to functional code, including parallel dispatch with the ">>" operator.
The Perforce Web Content Management System development team, lacking a pre-existing solution in PHP, designed and implemented their own object model and record layer to ease the interaction of the system with the Perforce Server. This session will focus on how users can access files in Perforce via a simple CRUD API, the subsystems exposed, and their usage.
Complet vector.dep.inc# This code depends on make tool being .docxardhowp
Complet vector/.dep.inc
# This code depends on make tool being used
DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES} ${TESTOBJECTFILES}))
ifneq (${DEPFILES},)
include ${DEPFILES}
endif
Complet vector/build/Debug/Cygwin-Windows/main.o
Complet vector/build/Debug/Cygwin-Windows/main.o.d
build/Debug/Cygwin-Windows/main.o: main.cpp SimpleVector.h
SimpleVector.h:
Complet vector/dist/Debug/Cygwin-Windows/complet_vector.exe
Complet vector/main.cppComplet vector/main.cpp/*
* File: main.cpp
* Author: Bebo
* Created on April 8, 2019, 6:18 PM
* Purpose:Complex Vector
*/
#include<cstdlib>
#include"SimpleVector.h"
//System Libraries
#include<iostream>//Input/Output Library
usingnamespace std;
//User Libraries
//Global Constants, no Global Variables are allowed
//Math/Physics/Conversions/Higher Dimensions - i.e. PI, e, etc...
//Function Prototypes
void fillVec(SimpleVector<int>&);
void addVec(SimpleVector<int>&);
void delVec(SimpleVector<int>&);
void prntVec(SimpleVector<int>&,int);
//Execution Begins Here!
int main(int argc,char** argv){
//Declare Variables
int size;
//Read in the size
cout<<"What size vector to test?"<<endl;
cin>>size;
SimpleVector<int> sv(size);
//Initialize or input i.e. set variable values
fillVec(sv);
//Display the outputs
prntVec(sv,10);
//Add and subtract from the vector
addVec(sv);
//Display the outputs
prntVec(sv,10);
//Add and subtract from the vector
delVec(sv);
//Display the outputs
prntVec(sv,10);
//Exit stage right or left!
return0;
}
void addVec(SimpleVector<int>&sv){
int add=sv.size()*0.1;
for(int i=1;i<=add;i++){
sv.push_front(i+add-1);
sv.push_back(i-add);
}
}
void delVec(SimpleVector<int>&sv){
int del=sv.size()*0.2;
for(int i=1;i<=del;i++){
sv.pop_front();
sv.pop_back();
}
}
void fillVec(SimpleVector<int>&sv){
for(int i=0;i<sv.size();i++){
sv[i]=i%10;
}
}
void prntVec(SimpleVector<int>&sv,int n){
cout<<endl;
for(int i=0;i<sv.size();i++){
cout<<sv[i]<<" ";
if(i%n==(n-1))cout<<endl;
}
cout<<endl;
}
Complet vector/Makefile
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed dire.
Slides from the GTA-PHP meetup about the new features in PHP 7. Slides had corresponding RFC pages linked to them in the speaker notes, but they don't seem to correspond to pages here so I've made the original keynote file available at http://gtaphp.org/presentations/NewInPHP7.zip and a PowerPoint version at http://gtaphp.org/presentations/NewInPHP7.pptx.
Let'Swift 2019 컨퍼런스에서 RxSwift to Combine 이라고 발표한 자료입니다. 자료 내에 언급되는 코드 링크는 다음과 같습니다.
[BringMyOwnBeer]
• RxSwift/RxCocoa: https://github.com/fimuxd/BringMyOwnBeer-
• Combine/SwiftUI: https://github.com/fimuxd/BringMyOwnBeer-Combine
From Java to Kotlin - The first month in practiceStefanTomm
This presentation shows the advantages and how easy it is for a Java developer to switch to Kotlin. There is also a sample project on github, that compares the two languages at the example of a Spring Boot application: https://github.com/Meshcloud/spring-kotlin-example
There is also a second version of these slides available on slideshare, as slideshare does not allow updating existing slides: https://www.slideshare.net/StefanTomm/from-java-to-kotlin-the-first-month-in-practice-v2
How to do Test Driven Development to write Chef cookbooks?
This slide-deck explains how to use TDD and tools of the trade, to develop cookbooks, Unit Tests and Integration Tests.
Source code is available on GitHub: https://github.com/siso/cheftdd-cookbook
Whether you call yourself a system administrator, developer, or DevOps sprint mediator, life is too short for sloppy shell scripts! In this talk, we look at how to improve them to stand the test of time. Michael will share how to create a good foundation for your scripts, so they run more reliable now and in the future. Your (future) colleagues might love you for it.
Focus areas of this presentation include error handling, security, style, and best practices. Also, it will cover (many) mistakes made by Michael over the last 20 years.
Lab Zero Lunchdown: Deploying Elixir and Phoenix Applicationsbrien_wankel
This Elixir deployment overview will recommend two different approaches to getting your application deployed.
You will learn about both containerized deploys and OTP deploys and the hope is to provide enough information that you can decide which is right for your situations.
The talk will also cover some common situations that must be considered when it comes to the Elixir build and deploy workflow.
Using the Groovy Ecosystem for Rapid JVM DevelopmentSchalk Cronjé
Overviewing Ratpack, Geb, Spock & Gradle to help with rapid development on the JVM. Mentions of other Gr8 tools & libraries. Swift introduction to Groovy.
The road to continuous deployment (DomCode September 2016)Michiel Rook
DomCode Meetup September 2016
It's there. The mountain. A giant monolith of code that blocks everything we do. But there's no rewriting it. What can we do? How can we continue? Don't worry, because this month's speaker Michiel Rook is here to help! He's going to speak from his experience tweaking, refactoring and replacing a...less than stellar...code base to Continuous Deployment.
It's a situation many of us are familiar with: a large legacy application, limited or no tests, slow & manual release process, low velocity, no confidence.... Oh, and management wants new features, fast.
But how to proceed? Using examples and lessons learned from a real-world case, I'll show you how to strangle a legacy application with a modern service architecture and build a continuous integration and deployment pipeline to deliver value from the first sprint. On the way, we’ll take a look at the process, automated testing, monitoring, master/trunk based development and various (possibly controversial!) tips and best practices.
From Zero to Application Delivery with NixOSSusan Potter
Managing configurations for different kinds of nodes and cloud resources in a microservice architecture can be an operational nightmare, especially if not managed with the application codebase. CI and CD job environments often tend to stray from production configuration yielding their results unpredictable at best, or producing false positives in the worst case. Code pushes to staging and production can have unintended consequences which often can’t be inspected fully on a dry run.
This session will show you a toolchain and immutable infrastructure principles that will allow you to define your infrastructure in code versioned alongside your application code that will give you repeatable configuration, ephemeral testing environments, consistent CI/CD environments, and diffable dependency transparency all before pushing changes to production.
With all of the focus on OOP and frameworks, sometimes the utilities get ignored. These modules provide us with lightweight, simple, effective solutions to everyday problems, saving us all from reinventing the wheel. This talk looks at a several of the utilities and shows some of the less common ways they can save a lot of time.
Nonparametric statistics show up in all sorts of places with fuzzy, ranked, or labeled data. The techniques allow handling messy data with more robust results than assuming normality. This talk describes the basics of nonparametric analysis and shows some examples with the Kolomogrov-Smirnov test, one of the most commonly used.
Using a base date, intervals, and ranges makes it easy to generate lookup tables for calendar intervals like annual or quarterly reports. The SQL for generating and searching the tables is made much easier using PG's built in range and interval types and more efficient with GiST indexes.
Performance benchmarks are all too often inaccurate. This talk introduces some things to look for in setting up and running benchmarks to make them effective.
A short description of the W-curve and its application to aligning genomic sequences. This includes a short introduction to the W-curve, example of SQL-based alignment of a crossover, suggestions for further work on its application.
A few general pointers for Perl programmers starting out to write tests using Perl6. This describes a few of the differences in handling arrays vs. hashes, comparing objects, flattening, and value vs. immutable object contents.
This describes a Functional Programming approach to computing AWS Glacier "tree hash" values, hiding the tail-call elimination in Perl5 with a keyword and also shows how to accomplish the same result in Perl6.
This was the talk actually given at YAPC::NA 2016 by Dr. Conway and myself.
Implementing Glacier's Tree Hash using recursive, functional programming in Perl5. With Keyword::Declare we get clean syntax for tail-call elimination. Result is a simple, fast, functional solution.
Short introduction to the use of non-parametric statistical analysis for quality assessment, general robust analysis of data. Includes a short introduction to the normal distribution and requirements for parametric analysis, review of binomial and poisson distributions, examples of non-parametric data, and example of using Kolomogrov-Smirnov. Final sections include references.
Shared Object images in Docker: What you need is what you want.Workhorse Computing
Docker images require appropriate shared object files (".so") to run. Rather than assume Ubuntu has the correct lib's, use ldd to get a list and install the ones you know you need. This can reduce the underlying images from GB to a few MB.
Logical Volume Management ("LVM") on linux looks like a complicated mess at first. The basics are not all that hard, and some features like mirroring, dynamic space management, snapshots for stable backups, mirroring, and over-provisioning via thin volumes can save a lot of time and effort.
Storing all of the reply content is usually not possible: it may be dynamic. A proxy allows directing only the content that needs to be handled locally to the test server, other content can go to the cloud. The final step, closing the loop between client and server, requires wapping LWP::UserAgent to direct locally handled requests to the test server.
Testing web front ends is a pain, partly because we end up testing the back end with them. Selenium helps by automating the input, but the selenium driver code lacks high-level interfaces for things like "find_and_click" or "find_and_key". Adding these with a wrapper makes data-driven selenium testing via Object::Exercise easy.
The perl on most linux distros is a mess. Docker makes it easier to build and packge a local perl and applications. Problem is that Docker's manuals produce a mess of their own.
Distributing perl on top of Gentoo's stage3 distro, busybox, or nothing at all made good alternatives. This talk includes basics of setting up docker, building a local perl for it, and packaging perl or applications into images for use in containers.
How to avoid Benchmark Stuff ("BS") evaluating performance of code. This installment uses time to compare the execution speed of Perl and various shell commands, with and without plumbing.
GraphSummit Singapore | The Art of the Possible with Graph - Q2 2024Neo4j
Neha Bajwa, Vice President of Product Marketing, Neo4j
Join us as we explore breakthrough innovations enabled by interconnected data and AI. Discover firsthand how organizations use relationships in data to uncover contextual insights and solve our most pressing challenges – from optimizing supply chains, detecting fraud, and improving customer experiences to accelerating drug discoveries.
Communications Mining Series - Zero to Hero - Session 1DianaGray10
This session provides introduction to UiPath Communication Mining, importance and platform overview. You will acquire a good understand of the phases in Communication Mining as we go over the platform with you. Topics covered:
• Communication Mining Overview
• Why is it important?
• How can it help today’s business and the benefits
• Phases in Communication Mining
• Demo on Platform overview
• Q/A
Securing your Kubernetes cluster_ a step-by-step guide to success !KatiaHIMEUR1
Today, after several years of existence, an extremely active community and an ultra-dynamic ecosystem, Kubernetes has established itself as the de facto standard in container orchestration. Thanks to a wide range of managed services, it has never been so easy to set up a ready-to-use Kubernetes cluster.
However, this ease of use means that the subject of security in Kubernetes is often left for later, or even neglected. This exposes companies to significant risks.
In this talk, I'll show you step-by-step how to secure your Kubernetes cluster for greater peace of mind and reliability.
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...Neo4j
Leonard Jayamohan, Partner & Generative AI Lead, Deloitte
This keynote will reveal how Deloitte leverages Neo4j’s graph power for groundbreaking digital twin solutions, achieving a staggering 100x performance boost. Discover the essential role knowledge graphs play in successful generative AI implementations. Plus, get an exclusive look at an innovative Neo4j + Generative AI solution Deloitte is developing in-house.
PHP Frameworks: I want to break free (IPC Berlin 2024)Ralf Eggert
In this presentation, we examine the challenges and limitations of relying too heavily on PHP frameworks in web development. We discuss the history of PHP and its frameworks to understand how this dependence has evolved. The focus will be on providing concrete tips and strategies to reduce reliance on these frameworks, based on real-world examples and practical considerations. The goal is to equip developers with the skills and knowledge to create more flexible and future-proof web applications. We'll explore the importance of maintaining autonomy in a rapidly changing tech landscape and how to make informed decisions in PHP development.
This talk is aimed at encouraging a more independent approach to using PHP frameworks, moving towards a more flexible and future-proof approach to PHP development.
The Art of the Pitch: WordPress Relationships and SalesLaura Byrne
Clients don’t know what they don’t know. What web solutions are right for them? How does WordPress come into the picture? How do you make sure you understand scope and timeline? What do you do if sometime changes?
All these questions and more will be explored as we talk about matching clients’ needs with what your agency offers without pulling teeth or pulling your hair out. Practical tips, and strategies for successful relationship building that leads to closing the deal.
Generative AI Deep Dive: Advancing from Proof of Concept to ProductionAggregage
Join Maher Hanafi, VP of Engineering at Betterworks, in this new session where he'll share a practical framework to transform Gen AI prototypes into impactful products! He'll delve into the complexities of data collection and management, model selection and optimization, and ensuring security, scalability, and responsible use.
GridMate - End to end testing is a critical piece to ensure quality and avoid...ThomasParaiso2
End to end testing is a critical piece to ensure quality and avoid regressions. In this session, we share our journey building an E2E testing pipeline for GridMate components (LWC and Aura) using Cypress, JSForce, FakerJS…
UiPath Test Automation using UiPath Test Suite series, part 5DianaGray10
Welcome to UiPath Test Automation using UiPath Test Suite series part 5. In this session, we will cover CI/CD with devops.
Topics covered:
CI/CD with in UiPath
End-to-end overview of CI/CD pipeline with Azure devops
Speaker:
Lyndsey Byblow, Test Suite Sales Engineer @ UiPath, Inc.
Threats to mobile devices are more prevalent and increasing in scope and complexity. Users of mobile devices desire to take full advantage of the features
available on those devices, but many of the features provide convenience and capability but sacrifice security. This best practices guide outlines steps the users can take to better protect personal devices and information.
2. FindBin::libs is a programatic “-I”
FindBin
Scan up the tree.
Use non-root ./lib dirs.
3. Why?
Test or execute project without installing.
In-house modules without CPAN or zef.
Tests use ./t/lib or ./t/etc
Avoid destructive tests in production.
Resolve path.
Use modules relative to ‘real’ path.
4. Describing Raku logic
Not Perl.
Coding & testing utilities.
Command line tools.
zef Installer.
Releasing with zef.
5. First Step: FindBin
You are here ---> *
Interactive vs. program.
Absolute path.
As-is vs. resolved.
Native filesystem.
&Bin &Script
7. “unit”
Raku uses “compilation units”.
This unit is a single module.
use v6.d;
unit module FindBin:ver<0.4.0>:auth<CPAN:lembark>;
8. “unit”
Raku uses “compilation units”.
Raku supports multiple versions & authors.
The version & author are part of the definition.
use v6.d;
unit module FindBin:ver<0.4.0>:auth<CPAN:lembark>;
10. Constant’s don’t change
Neither does your interactive status:
constant IS‑INTERACTIVE
= $*PROGRAM‑NAME eq '-e'| '-' | 'interactive'
;
11. Twigil
`tween a sigil and a name.
‘*’ is for dynamic.
AUTOGENERATED
constant IS‑INTERACTIVE
= $*PROGRAM‑NAME eq '-e'| '-' | 'interactive'
;
12. Module args
‘:’ prefix is part of the language:
use FindBin; # :DEFAULT
use FindBin :resolve;
use FindBin :verbose;
use FindBin :Bin;
use FindBin :Script :resolve;
13. Module args
‘:’ prefix is part of the language:
use FindBin; # :DEFAULT
use FindBin :resolve;
use FindBin :verbose;
use FindBin :Bin;
use FindBin :Script :resolve;
constant _FindBin_RESOLVE-DEF is export( :resolve ) = True;
constant _FindBin_VERBOSE-DEF is export( :verbose ) = True;
14. Slip
|( ) converts a list into a Slip.
No context: Raku lists don't flatten automatically.
Slips do.
Good examples at doc.raku.org (see references).
constant OPTION-TAGS = |( :resolve , :verbose );
16. Signature
An object.
Defines input, output.
sub Bin
(
Bool() :$resolve = CALLER::LEXICAL::_FindBin_RESOLVE-DEF,
Bool() :$verbose = CALLER::LEXICAL::_FindBin_VERBOSE-DEF
--> IO
)
17. Signature
:$resolve stores “:resolve” or “:!resolve” argument.
Defaults to caller’s lexical.
sub Bin
(
Bool() :$resolve = CALLER::LEXICAL::_FindBin_RESOLVE-DEF,
Bool() :$verbose = CALLER::LEXICAL::_FindBin_VERBOSE-DEF
--> IO
)
18. Signature
Bool() coerces the values to type Bool.
Avoids undef.
sub Bin
(
Bool() :$resolve = CALLER::LEXICAL::_FindBin_RESOLVE-DEF,
Bool() :$verbose = CALLER::LEXICAL::_FindBin_VERBOSE-DEF
--> IO
)
19. export
Explicit “:Bin”, no args.
Either of “:verbose” or “:resolve” via flattening.
sub Bin
(
Bool() :$resolve = CALLER::LEXICAL::_FindBin_RESOLVE-DEF,
Bool() :$verbose = CALLER::LEXICAL::_FindBin_VERBOSE-DEF
--> IO
)
is export( :Bin, :DEFAULT, OPTION-TAGS )
20. Using a constant
No sigil.
“?? !!” Ternary.
my $bin_from
= IS-INTERACTIVE
?? $*CWD
!! $*PROGRAM.IO
;
21. Using a constant
$*CWD is an IO. my $bin_from
= IS-INTERACTIVE
?? $*CWD
!! $*PROGRAM.IO
;
22. Using a constant
$*PROGRAM is Str.
.IO calls constructor:
Converts the string to
an IO object.
my $bin_from
= IS-INTERACTIVE
?? $*CWD
!! $*PROGRAM.IO
;
23. Using an IO
.resolve --> IO
.absolute --> Str.
my $path
= $resolve
?? $bin_from.resolve
!! $bin_from.absolute.IO
;
24. Returning a directory
dirname works on
*NIX, fails on
MS, VMS.
Parent includes
the volume.
IS-INTERACTIVE
?? $path
!! $path.parent
25. Bin
sub Bin
(
Bool() :$resolve = CALLER::LEXICAL::_FindBin_RESOLVE-DEF,
Bool() :$verbose = CALLER::LEXICAL::_FindBin_VERBOSE-DEF
--> IO
)
is export( :Bin, :DEFAULT, OPTION-TAGS )
{
my $bin_from
= IS-INTERACTIVE
?? $*CWD
!! $*PROGRAM.IO
;
my $path
= $resolve
?? $bin_from.resolve
!! $bin_from.absolute.IO
;
if $verbose { ... }
IS-INTERACTIVE
?? $path
!! $path.parent
}
Viola!
31. Generic sanity test
use v6.d;
use Test;
use lib $*PROGRAM.IO.parent(2).add( 'lib' );
( $*PROGRAM-NAME.IO.basename ~~ m{^ (d+ '-')? (.+) '.'t $} )
or bail-out 'Unable to parse test name: ' ~ $*PROGRAM-NAME;
my $madness = $1.subst( '-', '::', :g );
use-ok $madness;
my $found = ::( $madness ).^name;
is $found, $madness, "Package '$found' ($madness).";
done-testing;
32. Checking exports
Pseudo-class MY:: with hardwired name.
use v6.d;
use Test;
ok ! MY::<&Bin> , 'Bin not installed before use.';
ok ! MY::<&Script> , 'Script not installed before use.';
ok ! MY::<_FindBin_RESOLVE-DEF>, '! _FindBin_RESOLVE-DEF’;
ok ! MY::<_FindBin_VERBOSE-DEF>, '! _FindBin_VERBOSE-DEF’;
33. Checking exports
do
{
use FindBin;
ok MY::<&Bin> , 'Bin installed by default.';
ok MY::<&Script> , 'Script installed by default.';
ok ! MY::<_FindBin_RESOLVE-DEF>, '! _FindBin_RESOLVE-DEF';
ok ! MY::<_FindBin_VERBOSE-DEF>, '! _FindBin_VERBOSE-DEF';
note '# Bin is: ' ~ Bin;
note '# Script is: ' ~ Script;
};
34. Checking exports
do
{
use FindBin;
...
};
ok ! MY::<&Bin> , 'Bin is lexicaly scoped.';
ok ! MY::<&Script> , 'Script is lexicaly scoped.';
ok ! MY::<_FindBin_RESOLVE-DEF>, '! _FindBin_RESOLVE-DEF';
ok ! MY::<_FindBin_VERBOSE-DEF>, '! _FindBin_RESOLVE-DEF';
35. Script test program is easy
use v6.d;
use Test;
use lib $*PROGRAM.IO.parent(2).add( 'lib' );
use FindBin;
my $found = Script;
my $expect = $*PROGRAM.basename;
ok $found, 'Script returns ' ~ $found;
ok $expect, '$*PROGRAM.basename is ' ~ $expect;
is $found, $expect, 'Script matches basename.';
done-testing;
36. Testing -e takes more syntax
use v6.d;
use Test;
my $expect = '-e';
my ( $found )
= qx{ raku -I./lib -M'FindBin' -e 'say Script' }.chomp;
is $found, $expect, "'raku -e' returns '$found' ($expect)";
done-testing;
37. Now you got all of the tests...
How do you run them?
prove6; what you are used to
mi6 test; command line assistants
assixt test;
38. Releasing a module
“mi6 release;”
Changes entry
META6.json
Content pushed.
Assign a version tag.
Upload to CPAN.
39. Getting mi6
$ zef install App::Mi6
===> Searching for: App::Mi6
===> Testing: App::Mi6:ver<0.2.6>:auth<cpan:SKAJI>
===> Testing [OK] for App::Mi6:ver<0.2.6>:auth<cpan:SKAJI>
===> Installing: App::Mi6:ver<0.2.6>:auth<cpan:SKAJI>
1 bin/ script [mi6] installed to:
/opt/raku/share/raku/site/bin
Note the install dir.
Symlinks are your friends...
40. Changes
Revision history for FindBin
{{$NEXT}}
- Return IO for simplicity
0.3.4 2019-05-25T23:02:06-05:00
- use generic 01 test for use/require.
- POD, whitespace, comments.
0.3.3 2019-05-20T11:42:45-05:00
...
42. POD is still largely POD
=begin pod
=head1 SYNOPSIS
# export Bin() and Script() by default.
use FindBin;
my $dir_from = Bin(); # $dir_from is an IO object
my $script_base = Script(); # $script_base is a string.
# explicitly export only Bin() or Script().
use FindBin :Bin;
43. Releasing a module
$ mi6 release
==> Release distribution to CPAN
There are 12 steps: # Rakuholics Anonymous???
<snip>
==> Step 1. CheckChanges
==> Step 2. CheckOrigin
==> Step 3. CheckUntrackedFiles
==> Step 4. BumpVersion
Next release version? [0.3.5]: 0.4.0
==> Step 5. RegenerateFiles
==> Step 6. DistTest
<snip>
==> Step 8. UploadToCPAN
Are you sure you want to upload FindBin-0.4.0.tar.gz to CPAN? (y/N) y
44. Releasing a module
Housekeeping includes version tag.
==> Step 9. RewriteChanges
==> Step10. GitCommit
[master 6b2a3e2] 0.4.0
4 files changed, 5 insertions(+), 3 deletions(-)
<snip
To gitlab.com:lembark/Raku-FindBin.git
607929e..6b2a3e2 master -> master
==> Step11. CreateGitTag
Total 0 (delta 0), reused 0 (delta 0)
To gitlab.com:lembark/Raku-FindBin.git
* [new tag] 0.4.0 -> 0.4.0
==> Step12. CleanDist
45. Instant gratification
zef can install from a directory.
$ zef install . ;
===> Testing: FindBin:ver<0.4.0>:auth<CPAN:lembark>
# Madness: 'FindBin' (01-)
# FindBin
# Bin is: /sandbox/lembark/Modules/Raku/FindBin/t
<snip>
===> Testing [OK] for FindBin:ver<0.4.0>:auth<CPAN:lembark>
===> Installing: FindBin:ver<0.4.0>:auth<CPAN:lembark>
46. Bin is the root of all evil...
Next Step: Root out the rest of it.
Originally part of FindBin::libs:
Scan up directory tree.
Append relative paths.
Filter them.
48. Even more than more than one way to do it
multi scan-up
(
Stringy :$filter = 'all', *%argz
--> Seq
)
{
state %filterz =
(
all => True ,
dir => :d ,
file => :f ,
exist => :e ,
);
my $value = %filterz{ $filter }
or fail "Unknown: '$filter'. not "~ %filterz.keys.join(' ');
samewith filter => $value, |%argz
}
49. Single named arg “:filter”
multi scan-up
(
Stringy :$filter = 'all', *%argz
--> Seq
)
{
state %filterz =
(
all => True ,
dir => :d ,
file => :f ,
exist => :e ,
);
my $value = %filterz{ $filter }
or fail "Unknown: '$filter'. not "~ %filterz.keys.join(' ');
samewith filter => $value, |%argz
}
50. *%argz slurps remaining args
multi scan-up
(
Stringy :$filter = 'all', *%argz
--> Seq
)
{
stage %filterz =
(
all => True ,
dir => :d ,
file => :f ,
exist => :e ,
);
my $value = %filterz{ $filter }
or fail "Unknown: '$filter'. not "~ %filterz.keys.join(' ');
samewith filter => $value, |%argz
}
51. |%argz flattens them back out
multi scan-up
(
Stringy :$filter = 'all', *%argz
--> Seq
)
{
state %filterz =
(
all => True ,
dir => :d ,
file => :f ,
exist => :e ,
);
my $value = %filterz{ $filter }
or fail "Unknown: '$filter'. not "~ %filterz.keys.join(' ');
samewith filter => $value, |%argz
}
52. same name, new filter
multi scan-up
(
Stringy :$filter = 'all', *%argz
--> Seq
)
{
state %filterz =
(
all => True ,
dir => :d ,
file => :f ,
exist => :e ,
);
my $value = %filterz{ $filter }
or fail "Unknown: '$filter'. not "~ %filterz.keys.join(' ');
samewith filter => $value, |%argz
}
53. The other way to do it
multi scan-up
(
Any :$filter,
Str :$append = '',
Bool() :$resolve = False,
Bool() :$verbose = False,
Bool() :$skip-root = False,
IO() :$from = Bin( :$resolve, :$verbose )
--> Seq
)
is export( :DEFAULT )
$filter here is anything.
54. Args are defined in the parameters.
multi scan-up
(
Any :$filter,
Str :$append = '',
Bool() :$resolve = False,
Bool() :$verbose = False,
Bool() :$skip-root = False,
IO() :$from = Bin( :$resolve, :$verbose )
--> Seq
)
is export( :DEFAULT )
Re-cycled from Stringy multi via %args.
55. Telling them apart
multi Foo ( Stringy $filter = ‘all’, … )
multi Foo ( Any $filter, … )
Foo() Pick default no viable alternative.
Foo(‘X’) Pick Stringy derived from Any.
Foo( blah ) Pick Any.
56. Pick a filter, Any filter...
Perl5 used a code block, passed as a closure.
$filter->( $path ) or next...
57. Pick a filter, Any filter...
Smart matches are better way.
Pass in a file test, regex, block...
$path ~~ $filter or next;
58. Pick a filter, Any filter...
Smart matches are better way.
Pass in a file test, regex, block...
$path ~~ $filter or next;
Anything but a string.
Which was used up in the other multi.
59. Finding your path
absolute, resolve, parent should be familiar by now...
my $start =
(
$resolve
?? $from.resolve( completely => True )
!! $from
).absolute.IO;
my $path
= $start ~~ :d
?? $start
!! $start.parent
;
60. Finding your path
Fail if the path is not resolvable.
my $start =
(
$resolve
?? $from.resolve( completely => True )
!! $from
).absolute.IO;
my $path
= $start ~~ :d
?? $start
!! $start.parent
;
61. Gathering for a loop
return gather loop
{
…
take … if … ;
…
last if … ;
}
gather returns a Seq from take.
loop runs until a break.
Replaces for(;;){ ... push @result... }
62. Gathering for a loop
return gather loop
{
…
take … if … ;
…
last if … ;
}
gather returns a Seq from take.
loop runs until a break.
Replaces for(;;){ ... push @result... }
63. Gathering for a loop
return gather loop
{
…
take … if … ;
…
last if … ;
}
gather returns a Seq from take.
loop runs until a break.
Replaces for(;;){ ... push @result... }
64. Find your roots
return gather loop
{
my $next = $path.parent;
my $at-root = $path ~~ $next;
...
$path ~~ $filter
and take $path;
...
last if $at-root;
$path = $next;
}
65. What to take
if( $skip-root && $at-root )
{
say “Root: ‘$path’ (skip)” if $verbose;
}
else
{
my $take
= $append
?? $path.add( $append ) # add a relative path.
!! $path
;
$take ~~ $filter # $filter controls the match.
and take $take;
}
66. return gather loop
{
my $next = $path.parent;
my $at-root = $path ~~ $next;
if $at-root && $skip-root
{
note ‘Skip root’ if $verbose;
}
else
{
$take = $append ?? ... ;
$take ~~ $filter
and take $take;
}
$at-root
and last;
$path = $next;
}
Skip root before append.
Supply path to $filter.
Exit at root.
Working logic
74. Testing lazyness
One test: Compare it to an array.
my @found = scan-up.eager;
for ( 0 ..^ +@found ) -> $i { … }
Another is smart-match it with a seq:
my $found = scan-up;
ok $found ~~ $expect, ‘Found it.’;
75. Compare Bin dir with a file
Path and Bin results should match.
my $pass0 = scan-up;
ok $pass0, "scan-up = $pass0";
my $pass1 = scan-up :from( $*PROGRAM-NAME );
ok $pass1, "scan-up :from( $*PROGRAM-NAME ) = $pass1";
ok $pass0 ~~ $pass1, 'Bin matches $*Program-Name';
76. File and dir path work
$ Raku t/03-no-subdir.rakutest
ok 1 - scan-up = /sandbox/lembark/Modules/Raku/FileSystem-
Parent/t /sandbox/lembark/Modules/Raku/FileSystem-Parent
/sandbox/lembark/Modules/Raku /sandbox/lembark/Modules
/sandbox/lembark /sandbox /
ok 2 - scan-up :from( t/03-no-subdir.t ) =
/sandbox/lembark/Modules/Raku/FileSystem-Parent/t
/sandbox/lembark/Modules/Raku/FileSystem-Parent
/sandbox/lembark/Modules/Raku /sandbox/lembark/Modules
/sandbox/lembark /sandbox /
ok 3 - Bin and $*Program-Name return same list.
1..3
77. Adding a lib
:$append with variable name.
my $append = 'lib';
my $pass0 = scan-up :$append;
ok $pass0, 'scan-up $append';
my $pass1 = scan-up :$append, from => $*PROGRAM-NAME;
ok $pass1, 'scan-up $append :from => $*PROGRAM-NAME';
ok $pass0.eager ~~ $pass1.eager, ‘They match’;
78. Testing :$append
ok 1 - scan-up $append
ok 2 - scan-up $append :from => $*PROGRAM-NAME
# Pass0:/sandbox/lembark/Modules/Raku/FileSystem-Parent/t/lib
/sandbox/lembark/Modules/Raku/FileSystem-Parent/lib
/sandbox/lembark/Modules/Raku/lib
/sandbox/lembark/Modules/lib /sandbox/lembark/lib /sandbox/lib
/lib
# Pass1:/sandbox/lembark/Modules/Raku/FileSystem-Parent/t/lib
/sandbox/lembark/Modules/Raku/FileSystem-Parent/lib
/sandbox/lembark/Modules/Raku/lib
/sandbox/lembark/Modules/lib /sandbox/lembark/lib /sandbox/lib
/lib
ok 3 - Bin and $*Program-Name return same list.
79. Test verbose overrides
There is, of course, more than one way.
Shouldn’t affect Bin’s return value.
use FindBin :verbose;
my $false_1 = Bin( verbose => False ).Str;
my $false_2 = Bin( :verbose( False ) ).Str;
my $false_3 = Bin( :!verbose ).Str;
is $false_1, $false_2, "Match with false.";
is $false_2, $false_3, "Match with false.";
82. “EXPORT” does the deed
Outside of the package.
Handles positionals passed via use.
use v6.d;
sub EXPORT
(
*@args –-> Map
)
{
my $resolve = ? @args.first( 'resolve' );
my $verbose = ? @args.first( 'verbose' );
# do things...
}
unit module FindBin::libs:ver<0.0.1>:auth<CPAN:lembark>
# ain’t nobody here but us chickens
83. “EXPORT” does the deed
Outside of the package.
Handles positionals passed via use.
use v6.d;
sub EXPORT
(
*@args –-> Map
)
{
my $resolve = ? @args.first( 'resolve' );
my $verbose = ? @args.first( 'verbose' );
# do things...
}
unit module FindBin::libs:ver<0.0.1>:auth<CPAN:lembark>
# ain’t nobody here at all
84. Raku Colon Cleanser
Ever loose track of parens in an expression?
Raku method calls can replace
$foo.some_method( $bar );
with
$foo.some_method: $bar;
85. Raku Colon Cleanser
Ever loose track of parens in an expression?
Convert:
$foo.frob($bar.nicate($thing.new($blort)));
into:
$foo.frob: $bar.nicate: $thing.new: $blort
86. Raku Colon Cleanser
Ever loose track of parens in an expression?
$foo.frob:
$bar.nicate:
$thing.new: $blort
;
93. Named Parameters & Variables
Egads! Using “:$prefix” ties your code to an API!
94. Named Parameters & Variables
Egads! Using “:$prefix” ties your code to my API!
Signatures allow arbitrary variable names.
:$prefix is a shortcut for
sub foo( :prefix( $prefix ) )
You can also have:
sub foo ( :prefix( $dir_pref ) )
Change internal variable names.
95. Named Parameters & Variables
Egads! Using “:$prefix” ties your code to my API!
Signatures allow arbitrary variable names.
:$prefix is a shortcut for
sub foo( :prefix( $prefix ) )
You can also have:
sub foo ( :add( $prefix ) )
Change external parameter name.
96. --> Map
sub EXPORT
(
*@args --> Map
)
{
# return a Map
%( '@FindBin-libs-dirs' => @found )
}
Map of ( Name => Value )
97. --> Map
Map of ( Name => Value )
‘@’ is part of the name.
sub EXPORT
(
*@args --> Map
)
{
# return a Map
%( '@FindBin-libs-dirs' => @found )
}
98. sub EXPORT
(
*@args --> Map
)
{
use FileSystem::Parent;
my $resolve = ? @_.first( 'resolve' );
my $verbose = ? @_.first( 'verbose' );
my %fixed = ( ... );
my @found
= scan-up( :$verbose, :$resolve, |%fixed );
for @found.reverse -> $prefix
{
CompUnit::RepositoryRegistry.use-repository:
CompUnit::Repository::FileSystem.new:
:$prefix
}
%( '@FindBin-libs-dirs' => @found )
}
Exporter
99. “unit” is a placeholder.
Export does all the work.
unit module FindBin::libs has no subs.
100. Pass1: Check for installed dirs.
EXPORT installs the variable.
Flatten it for printing.
use FindBin::libs;
ok @FindBin-libs-dirs, 'Exported FindBin-libs-dirs';
note join( "n#t", '# libs:', |@FindBin-libs-dirs );
done-testing;
101. Pass2: Validate directory order.
Frobnicate.rakumod in ./t/lib/FindBin & ./lib/FindBin.
“FrobPath” will be ‘t/lib/...’ or ‘lib/...’.
unit module FindBin::Frobnicate:ver<0.1.1>:auth<CPAN:lembark>;
constant FrobPath is export( :DEFAULT )
= 't/lib/FindBin/Frobnicate.pm6';
constant FrobPath is export( :DEFAULT )
= 'lib/FindBin/Frobnicate.pm6';
102. Pass2: Validate directory order.
Test in ./t should prefer t/lib.
use FindBin::libs;
use FindBin::Frobnicate;
ok MY::<FrobPath>, 'FrobPath exported.';
my $expect = 't/lib/FindBin/Frobnicate.pm6';
my $found := MY::FrobPath;
is $found, $expect, "Found: ‘$found’”;
103. prove6
Looks familiar.
$ prove6 -v t/03-use-frobnicate.t;
ok 1 - FrobPath exported.
ok 2 - Found 't/lib/FindBin/Frobnicate.pm6'
1..2
t/03-use-frobnicate.t .. ok
All tests successful.
Files=1, Tests=2, 0 wallclock secs
Result: PASS
104. Summary
Raku is quite doable.
mi6 & assixt make it manageable.
Raku has gotten much better.
Raku is quite doable.
mi6 & assixt make it more manageable.
The doc’s website has gotten much better:
Raku
Try it... you’ll like it.